From e0f9883cbaba4bc49ecb5f77284af36937cb1248 Mon Sep 17 00:00:00 2001 From: Jordi Sanfeliu Date: Mon, 22 Oct 2012 16:26:37 +0200 Subject: [PATCH] uploaded latest version --- COPYING | 339 + Changes | 896 +++ README | 170 + README.FreeBSD | 18 + README.NetBSD | 19 + README.OpenBSD | 20 + README.nginx | 31 + docs/monitorix-alert.sh | 29 + docs/monitorix-apache.conf | 32 + docs/monitorix-deb.init | 88 + docs/monitorix-lighttpd.conf | 4 + docs/monitorix.init | 87 + docs/monitorix.logrotate | 7 + docs/monitorix.spec | 96 + docs/monitorix.sysconfig | 3 + logo_bot.png | Bin 0 -> 1870 bytes logo_top.png | Bin 0 -> 4021 bytes man/man5/monitorix.conf.5 | 1768 +++++ man/man8/monitorix.8 | 57 + monitorix | 7005 +++++++++++++++++ monitorix.cgi | 13765 +++++++++++++++++++++++++++++++++ monitorix.conf | 1022 +++ monitorixico.png | Bin 0 -> 2251 bytes reports/ca.html | 74 + reports/de.html | 74 + reports/en.html | 74 + reports/it.html | 74 + reports/pl.html | 74 + reports/send_reports | 165 + 29 files changed, 25991 insertions(+) create mode 100644 COPYING create mode 100644 Changes create mode 100644 README create mode 100644 README.FreeBSD create mode 100644 README.NetBSD create mode 100644 README.OpenBSD create mode 100644 README.nginx create mode 100755 docs/monitorix-alert.sh create mode 100644 docs/monitorix-apache.conf create mode 100755 docs/monitorix-deb.init create mode 100644 docs/monitorix-lighttpd.conf create mode 100755 docs/monitorix.init create mode 100644 docs/monitorix.logrotate create mode 100644 docs/monitorix.spec create mode 100644 docs/monitorix.sysconfig create mode 100644 logo_bot.png create mode 100644 logo_top.png create mode 100644 man/man5/monitorix.conf.5 create mode 100644 man/man8/monitorix.8 create mode 100755 monitorix create mode 100755 monitorix.cgi create mode 100644 monitorix.conf create mode 100644 monitorixico.png create mode 100644 reports/ca.html create mode 100644 reports/de.html create mode 100644 reports/en.html create mode 100644 reports/it.html create mode 100644 reports/pl.html create mode 100755 reports/send_reports diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/Changes b/Changes new file mode 100644 index 0000000..ec4d2de --- /dev/null +++ b/Changes @@ -0,0 +1,896 @@ +2.6.1 - NN-XXX-2012 +==================== +- Introduced some modifications to the device name detection for FreeBSD. + (thanks to Chris Rees, utisoft AT gmail.com) + + +2.6.0 - 19-Sep-2012 +==================== +- Added a complete statistical BIND graph. +- Added support for NetBSD systems. +- Added support for grouping remote servers in the Multihost view. + (thanks to Hartmut Wöhrle, hartmut AT hartmut-woehrle.ch) +- The Disk and Filesystems Usage and I/O Activity graphs have been completely + rewriten. + (suggested by Konstantinos Skarlatos, k.skarlatos AT gmail.com) +- Added support to monitor unlimited number of disk drives. +- Added support to monitor unlimited number of filesystems. +- Reorganized the legend in the Disk drive temperatures and health graph. +- Changed the shebang to be more portable among different systems. +- Completely rewritten the Debian/Ubuntu init script. + (suggested by Andreas Itzchak Rehberg, izzy AT qumran.org) +- Minor changes in the header of the Debian/Ubuntu init script. + (thanks to Uwe Heidrich, uweheidrich AT hotmail.com) +- Expanded to 15 characters the description in network ports. +- Changed to lines a bit thicker some graphs with few values. +- Added a new feature to enable/disable the use of javascript:void function when + clicking on a zoomable graph. + (thanks to Florian E.J. Fruth, fejf AT gmx.de) +- Fixed a bug that mixed the collected values when monitoring multiple MySQL + servers. + (thanks to Piotr Smalira, p.smalira AT g16-lublin.eu) +- Fixed a bad percentage calculation in the dentries and inodes values. +- Removed useless code when collecting Squid stats. +- Fixed a typo in a MySQL graph. + + +2.5.2 - 21-May-2012 +==================== +- Modified iptables/ipfw accounting rules handling and fixed some bugs. +- Added to backup .rrd files every time it changes their internal structure. + (suggested by Michael Mansour, mmansour AT ostech.com.au) +- Fixed a bug that prevented the creation of the 'mysql.rrd' file. The error + message was "ERROR: while creating /var/lib/monitorix/mysql.rrd: you must + define at least one Data Source". + (thanks to Darryl Yeoh Gim Hong, drl AT bsd.my for pointing this out) +- Fixed to avoid modifying read-only values in chomp() function. + (thanks to Julio Cifuentes, jcifuentes AT mail.com for pointing this out) + + +2.5.1 - 23-Apr-2012 +==================== +- Modified the regexp in 'mgr:ipcache' listing to support newer Squid versions. +- Changed some information and debug messages to be more verbose and clear. +- Force termination with exit(0) when receiving a SIGINT. +- Added support to use the socket file for the connection to the MySQL server. + (suggested by Darryl Yeoh Gim Hong, drl AT bsd.my) +- Added the new option IMAP_DATE_LOG_FORMAT to match with the Dovecot date log + format. +- Refreshed the COPYING file to reflect the current contents of the GPLv2 at + http://www.gnu.org/licenses/gpl-2.0.txt. +- Complete English correction in the monitorix.conf(5) man page. + (thanks to Paul Rupp, paulrupp AT acorp.net) +- Fixed a bug that prevented monitoring multiple MySQL servers. + (thanks to Piotr Smalira, p.smalira AT g16-lublin.eu) +- Fixed the vertical label of network traffic in Mail graph to honour the + NETSTATS_IN_BPS option. + (thanks to Piotr Smalira, p.smalira AT g16-lublin.eu) +- Fixed a bug that prevented collecting IMAP data from wu-imap server. +- Fixed padding on big values in the Nginx stats. + + +2.5.0 - 21-Mar-2012 +==================== +- Added a complete statistical Fail2ban graph. + (suggested by Andreas Itzchak Rehberg, izzy AT qumran.org) +- Added a complete statistical Lighttpd graph. +- Added full support for the Postfix MTA in the Mail statistics graph. +- Extended the number of information in the Mail statistics graph. +- Added support to monitor unlimited number of local or remote Apache servers. +- Added support to monitor unlimited number of local or remote MySQL servers. +- Added support for Dovecot 2.0 log format. +- Optimized a lot of code including more regular expressions. +- Replaced hardcoded graph titles with the strings in the configuration file. +- Modified the RedHat init script to let Monitorix create itself the pidfile. + This should improve the support on modern Linux systems using 'systemd'. + (thanks to a IRC user called 'dashbad' for pointing this out) +- Improved the init script to be more LSB-compliant. +- Changed to the '-A' parameter in 'smartctl' to avoid waking up disks when + collecting their temperatures and health values. + (thanks to Michael Perry, mike AT serensilver.co.uk) +- Fixed some titles in the list box of the main page. +- Fixed color overriding in the IMAP and POP3 services graph. +- Fixed the title in some graphs. +- Fixed a typo in the debug array name that prevented individual debug working + properly. +- Fixed a typo in the configuration file. + (thanks to a IRC user called 'gangsterlicious' for pointing this out) +- Fixed a bug in the Squid graph that prevented of being counted the Aborted + clients. +- Fixed numbering in some graphs. + + +2.4.1 - 09-Jan-2012 +==================== +- Added support for Dovecot 1.2 log format. +- Added Polish language support in the monthly traffic report. + (thanks to Piotr Smalira, p.smalira AT g16-lublin.eu) +- Added 'hour' timeframe in 'monitorix.cgi' to accept unsupported queries not + comming from the main page. +- Added support for fail2ban bans in the System Services Demand graph. + (thanks to Andreas Itzchak Rehberg, izzy AT qumran.org) +- Added support for CommuniGate mail server logs in the System Services Demand + graph. + (thanks to Andreas Itzchak Rehberg, izzy AT qumran.org) +- Added the ability to show more debug information introducing extra values to + the -d parameter. The monitorix(8) manpage has been updated to reflect these + changes. + (suggested by Andreas Itzchak Rehberg, izzy AT qumran.org) +- Added the sensor real names in the Voltages graph. + (suggested by Andreas Itzchak Rehberg, izzy AT qumran.org) +- Removed duplicated newline character in logger() calls. +- Added disabling automatic page reloading when $REFRESH_RATE is 0. + (thanks to Andreas Itzchak Rehberg, izzy AT qumran.org) +- Added a new option in configuration file to change the favicon image. + (thanks to Andreas Itzchak Rehberg, izzy AT qumran.org) +- Added support for SpamAssassin and Clamav logs to catch email-spam and + email-virus. + (thanks to Andreas Itzchak Rehberg, izzy AT qumran.org) +- Grouped all the mail related services to the small graphs in the System + Services Demand graph. This only implied changing the IMAP position. + (suggested by Andreas Itzchak Rehberg, izzy AT qumran.org) +- Fixed the main interrupt graph in order to avoid running out of colors on + systems with lot of interrupts. +- Fixed to honour the limit of 15 characters of the mountpoint names in the + Icecast graph. +- Fixed the column layout of the text mode in the LM-Sensors graph. +- Fixed to set standard locale LC_TYPE,"C". + + +2.4.0 - 28-Nov-2011 +==================== +- Added a complete statistical Squid Proxy Web Cache graph. + (suggested by Michael Mansour, mmansour AT ostech.com.au) +- Added a complete statistical NTP multigraph. +- Added a complete statistical Icecast Streaming Media Server multigraph. + (suggested by Kamil Weiser, crx AT lordcyber.net) +- Error messages now use the internal logger() function so all these messages + will have the date and time prefixed. +- Added support for network port monitoring on FreeBSD and OpenBSD systems. +- Added support for Nginx network traffic monitoring on FreeBSD and OpenBSD + systems. +- Added the number of instances (1) in the specified time key (day, week, month + or year). This also introduces some changes in the name of the .png files and + will break backwards compatibility with old (2.3-) Monitorix with Multihost + feature enabled. +- Removed some inadequate calls to 'die' taking proper actions on each case. +- Introduced small optimizations. +- Removed the '--lower-limit=0' in the Voltages graph that prevented seeing + negatives values. +- Fixed some typos in the variable name $PNG_DIR in 'monitorix.cgi'. +- Fixed to avoid a 'divide by zero' message on certain NVIDIA driver version. + + +2.3.0 - 05-Sep-2011 +==================== +- Added a complete statistical NFS (v2, v3 and v4) server graph. +- Added a complete statistical NFS (v2, v3 and v4) client graph. +- Improved support for newer NVIDIA drivers and fixed some bugs. +- Added the 'condrestart' option in the RedHat init script. + (suggested by Yury V. Zaytsev, yury AT shurup.com) +- Added a new option in the configuration file to toggle all network values + between bits and bytes per second. +- Some cosmetic changes. +- Fixed to sanitize a trailing space in the '/proc/stat' file that prevented to + show values in the disk I/O graphs on certain systems with Linux kernel 2.4. + (thanks to Dimitri Yioulos, dyioulos AT firstbhph.com) +- Fixed the Connections_usage value in the MySQL graph avoiding to be greater + than 100%. +- Fixed to avoid showing the device interrupts called 'Dynamic-irq'. + (thanks to Michael Mansour, mmansour AT ostech.com.au) +- Fixed to avoid showing the additional parameter in disk drives. + (thanks to Michael Mansour, mmansour AT ostech.com.au) +- Fixed to add more colors in order to support more interrupt devices. + (thanks to Dan Criel, dancriel AT gmail.com) +- Fixed a bad calculation of network traffic in 'text' interface of Ports graph. +- Fixed an extra 'optgroup' close tag in 'index.html' for each graph disabled. + + +2.2.0 - 21-Jun-2011 +==================== +- Added support for OpenBSD systems. + (thanks to Devio.us team) +- Added a complete statistical MySQL graph. + (thanks to Luca Ferrario, luca AT ferrario.net) +- (missed in previous version) Prefixed with full path the 'sysctl' command to + retrieve the boot time. This is specially needed when using the lighttpd web + server on FreeBSD systems. + (thanks to Chris Rees, utisoft AT gmail.com) +- Added the Fork rate (new processes started per second) in the Context Switches + graph. It includes two new values: the number of forks and vforks, being the + later only for FreeBSD and OpenBSD systems. +- Added support for the new NVIDIA driver 270.41.03. +- Added support for the names 'BusyServers' and 'IdleServers' given by Apache + when ExtendedStatus is disabled. +- Added support to show the interrupt names on Xen guest systems. +- Added to force a standard locale to avoid problems with decimal point/comma. + (thanks to Vadim Beljaev, anon333 AT mail.com) +- Workarounded the well-known problem with SIG{CHLD} and system() function that + returns -1 on *BSD systems. +- Included a Debian init script. + (thanks to Jörg Alpers, JAlpers AT gmx.net) +- Fixed the LINE2 of VFS graph and the swap device in FS graph. +- Fixed a bug when counting total of users on systems with large number of users + logged in. +- Fixed a bug in 'monitorix.spec' that prevented a correct installation on + systems with no 'apache' user defined, and added cosmetic changes. +- Fixed to show only the graphs of the PC LAN defined in @PC_LIST even when + $PC_MAX is greater. +- Fixed a bug that could remove some Network Port 'iptables' rules under + certain circumstances. +- Fixed a bug that prevented to put in the email of monthly reports the listing + with the daily usage of all the hosts. +- Fixed a missing import of the 'File::Basename' module. +- Fixed some typos in the man pages and aligned texts in some graphs. + + +2.1.2 - 04-May-2011 +==================== +- Added a new command line parameter to save the PID into the specified file + in order to make life easier to 'rc' scripts. + (thanks to Chris Rees, utisoft AT gmail.com) +- Prefixed with full path the 'sysctl' command to retrieve the boot time. This + is specially needed when using the lighttpd web server on FreeBSD systems. + (thanks to Chris Rees, utisoft AT gmail.com) +- Added to change to the / directory before parsing the command line parameters, + and after that, a change to a safety directory, either /tmp or /lost+found. +- Improved the code that detects the physical device name where the / filesystem + resides. +- Changed the way how are handled the command line options. +- Removed the 'Tahoma' font name from all 'font face' HTML tags. +- Hidden the unused values in the 'LM-Sensors and GPU temperatures' graphs. +- Fixed to remove correctly the 'iptables' rules when some defined port has been + removed from the configuration file. +- Fixed to show only the graphs of the ports defined in @PORT_LIST even when + $PORT_MAX is greater. +- Fixed a missing variable initialization that generated an 'illegal division by + zero' message if the filesystem defined does not existed, and the system + didn't had a valid swap device. + (thanks to Mowd, mowd8574 AT gmail.com) +- Fixed to show the PID number even when started as a foreground process. +- Fixed the padding of the Voltages values. +- Fixed a bug that prevented to gather correctly the disk I/O values of the / + filesystem on Linux systems with kernel 2.4. + + +2.1.1 - 12-Apr-2011 +==================== +- Reflect the SIGHUP reception with a message also in the new reopened log file. +- Added support for the new 'Idrop' column in the output of 'netstat' command + appeared in FreeBSD 8.0 and newer versions. + (thanks to Sean, strumming AT thestrings.com) +- Fixed an illegal division by zero message if the swap device is not used at + all, which caused to not collect any data and, at the same time, prevented to + see any results in the Filesystems usage and I/O activity graphs. + (thanks to Daniel Constantinov, daniel AT k9tecnologia.com.br) +- Fixed to not show a broken graph if there is no data defined in any of the + three possible arrays of the HP Temperatures graphs. +- Fixed to rename the files in the $USAGE_DIR directory once they are already + sent in the monthly reports. +- Fixed to create correctly the iptables rules for PC LAN traffic accounting. + (thanks to Daniel Constantinov, daniel AT k9tecnologia.com.br) + + +2.1.0 - 09-Mar-2011 +==================== +- Completed the monthly traffic reports for PCs. +- Added a better signal handling. +- Added the SIGHUP signal handler in order to close and open a new log file. +- Modified the monitorix(8) manpage to reflect that new feature. +- Darkened the grey color of the CUPS usage in the Network Services graphs. +- Fixed annoying messages in log file when PC_MAX is actually greater than the + number of entries in PC_LIST or PC_IP: + +*** DNS problem with: +*** pc_update(): Usage: Socket::inet_ntoa(ip_address_sv) at /usr/bin/monitorix line 3548. + +- Fixed to show only the entries defined in PC_LIST even when PC_MAX has a + greater value. +- Fixed to correctly handle the SIGCHLD signal to prevent an accumulation of + defunct or "zombie" processes in old Perl versions. +- Fixed a regexp in 'fs.rrd' that prevented monitoring non-local filesystems. +- Fixed a typo in monitorix(8) man page when referencing the monitorix.conf(5) + man page. +- Fixed in 'monitorix.cgi' to accept the 'silent' option in PCs graphs. +- Fixed to LINE2 type the lines plotted in the Greylisting zoomed graph. + + +2.0.0 - 01-Feb-2011 +==================== +This new version is a complete rewrite, including new features and graphs, +cleaned up all the code, updated and enhanced a number of aspects in some +graphs, and fixed a lot of bugs. The most important change is that it no longer +requires 'crond' to work, instead Monitorix is now a complete standalone Perl +daemon being started and stopped like any other system service. + +Please read the 'News' and 'Features' sections in the Monitorix web site to +give you an idea of all the changes and new features that include. + +I want to give a huge thanks to the people that has contributed testing and +reporting bugs during its beta phase. + + +1.5.2 - 18-Nov-2010 +==================== +- Added an new alert based on the usage of the root filesystem. It follows + the same logic than the CPU alert, so the alert script is practically the + same. + (thanks to Ramchander, ramchan10 AT gmail.com) +- Modified the man page of the configuration file to reflect the new alert + capability. +- Added a protection mechanism when collecting the filesystem disk usage. It + prevents possible timeout scenarios on those filesystems mounted using NFS. + (thanks to Ramchander, ramchan10 AT gmail.com) +- Fixed to remove the netmask suffix when collecting the network traffic if + the IP belongs to a hostname instead of a network. + (anonymous contribution) + + +1.5.1 - 23-Jun-2010 +==================== +- Changed the default $ENABLE_MAIL option to 'N'. +- Added a second decimal in the Mail statistics graph in order to have more + accurated values. +- Added a missing "--lower-limit=0" to all graphs (except MTA stats). +- Changed the default value of rigid (RIGID = 2) to 0 in all network port graphs. +- Included a number of necessary adjustments in the install.sh script to adapt + it better to the FreeBSD installation process. + (thanks to Michael Brune, admin AT mjbrune.org) +- Added the description of the @NET_RIGID and @NET_LIMIT arrays in the man page + monitorix.conf(5). +- Fixed some bugs and a bad code design in the Interrupts graph that prevented + showing correctly the graph on systems with some interrupts numbers greater + than 256. + (thanks to Dimitri Yioulos, dyioulos AT firstbhph.com) +- Fixed the Memory graph to display correctly the value in MB. This bug affected + only the FreeBSD systems. +- Fixed to be able to enable only the LAN devices monitoring without having to have + enabled the network ports monitoring. + (thanks to Niklas Janzon, niklas.janzon AT gmail.com) +- Fixed the iptables rules section in order to avoid its execution on FreeBSD + systems. +- Fixed a bug in the init script that prevented executing it during the system + shutdown on RedHat/Fedora/CentOS systems. The path of the lock file has + changed from /var/lock/ to /var/lock/subsys. + + +1.5.0 - 06-Apr-2010 +==================== +- Added a new graph to show complete MTA (Sendmail) statistics. +- Added support for those lines in the 'sensors' command output that include + a newline character and have the result in the next line. + (thanks to Balazs Denes, dnsdns AT gmail.com) +- Reused a lot of temporal variables in the CGI file. +- Fixed to not show error messages on certain virtual servers if the file + '/proc/diskstats' does not exist. + (thanks to an anonymous IRC user called 'gangsterlicious') +- Fixed the rigid control in the 3rd graph of the Nginx statistics. +- Fixed the colors scheme in the main page when using the 'white' theme. + + +1.4.2 - 10-Feb-2010 +==================== +- Removed the width=1 from the top table in the graphs page. +- Changed to grey the color of all links. +- Added automatic detection of total amount of memory in the system. +- Modified the install.sh script in order to remove the already supported + distribution Gentoo and to include some warnings saying that the script is + not the recommended method of installing Monitorix. +- Added a new $OSTYPE key called "Linux-Arch" to include support for Arch Linux + distribution. + (thanks to graysky, da_audiophile AT yahoo.com) +- Fixed the URL of the images if is being called through a secure web server. + (thanks to an anonymous IRC user called 'dobermai') +- Fixed those no named interrupts that generated the annoying message + "substr outside of string at /var/www/cgi-bin/monitorix.cgi line 4775, + line n." in the Apache error log. + (thanks to Mac, redleader25 AT hotmail.com) + + +1.4.1 - 04-Jan-2010 +==================== +- Updated the monitorix.spec and monitorix.conf files for SuSE Linux packages. + (thanks to Oliver Kaltenecker, oliver.kaltenecker AT wittwer.de) +- Modified the wide of the mount point column in the disk usage graph in order + to fit longer pathnames. +- Substituted the pair of bottom logos (black and white) for a new one with + background transparency. +- Changed the initial logo image by a new one with background transparency and + removed the slogan which reduced its size. +- Removed the configuration option $IDATE. +- Removed the envelope image as with the new mailing list it doesn't make sense + to be there anymore. +- Fixed to honour the color theme even in the main page and simplified its + layout. +- Fixed some annoying error messages in the web server logs about the use of + an uninitialized value in 4781 line. + (thanks to Edgar Barranco, ebarranco AT gmail.com) +- Fixed a bug in how are collected the hardware temperatures in HP ProLiant + ML310 and ML350 models. + (thanks to Rene Kapeller, rene.kapeller AT psi.ch) +- Fixed an overflow in the CPU array in systems with more than 8 processors, + that prevented seeing the rest of graphs. + (thanks to Robin Friedrich, Robin.Friedrich AT itt.com) + + +1.4.0 - 05-Oct-2009 +==================== +- Optimized the iptables command used to collect Chain statistics. +- Added the ability to show the results in plain text instead of using rendered + graphs. This will make life easier either for people with vision impairments + and for automatic processing of the information. + (thanks to Christoph Doeren, cd AT yuyumo.de) +- Added an alert system based on the last 15 minutes of the CPU load average. + (suggested by Dimitri Yioulos, dyioulos AT firstbhph.com) +- Fixed a bug in monitorix.cgi that messed up the way how are displayed the + individual processors' graphs. + + +1.3.2 - 01-Sep-2009 +==================== +- Improved a lot the support for FreeBSD systems. + (thanks to Pavlin Vatev, anex AT smrad.net) +- Added support for Enterprise Volume Management System (EVMS) to show the + I/O disk activity of the root filesystem. + (thanks to Markus Rennings, mren AT mrmx.de) +- Added a new option in monitorix.conf called %MAIL_LOG with the paths for the + mail log file of each Operating System. This removes the old path hard coded. +- Changed the "use" line of the LWP::UserAgent module, now is only loaded if + Nginx statistics are enabled. This creates less dependences for all people + that don't need the Nginx statistics. +- Optimized the accounting process of SSH connections using the same code for + Linux and for FreeBSD. Linux SSH connections using public keys are also + counted now. + (thanks to Markus Rennings, mren AT mrmx.de) +- Rewritten the Monitorix init script for Gentoo Linux. + (thanks to Markus Rennings, mren AT mrmx.de) +- Added a zero pading in the name of the proc.png files. +- Fixed to show 0% of usage if a filesystem defined in MNT_LIST has been + umounted, instead of returning the same disk usage of its parent filesystem. +- Fixed the %HTTP_LOG path in the monitorix.conf file for Linux-Gentoo. + (thanks to Markus Rennings, mren AT mrmx.de) +- Fixed the missing monitorixico.png file in the install script. + (thanks to Markus Rennings, mren AT mrmx.de) +- Fixed to not create the network ports counters if $ENABLE_PORT is "N". + + +1.3.1 - 05-Jul-2009 +==================== +- Fixed a location problem for the logo files on a fresh installation using the + Linux-Debian option. +- Fixed a critical permission problem during a fresh installation (using the + Linux-Debian option) that prevented seeing all the graphs. + (thanks to Rubla Georgian, deletet.file AT yahoo.com) +- Fixed some annoying error messages in the web server log when the $PORTnn and + $PORTnn_NAME aren't correctly defined in /etc/monitorix.conf. + (thanks to Luca Ferrario, luca AT ferrario.net) +- Removed the un_install.sh script. + + +1.3.0 - 14-Jul-2009 +==================== +- Added the monitorix.conf(5) man page to be the main place to get help. +- Added support for the Nginx web server statistics. + (thanks to Aleksandr Miroshnychenko, al.miroshnychenko AT gmail.com) +- Removed the unused $EMAIL option. The $PC_DEFMAIL option is the one used when + sending the monthly reports. +- Removed the $PC_MAX option as its value is now hard coded. +- Reorganized a bit the monitorix.conf file and cleared the syntax. +- Improved the install.sh script with the 'install' command instead of using + 'mkdir', 'cp' and friends. +- Fixed some missing HTML closing tags. +- Fixed to match the default value of $ENABLE_LMTEMP in monitorix.pl. +- Fixed a bad counting of the number of current Samba shares when there wasn't + any share on the list. + (thanks to Luca Ferrario, luca AT ferrario.net) + + +1.2.4 - 06-Apr-2009 +==================== +- Isolated a Linux dependant code that prevented running Monitorix correctly + on FreeBSD systems. +- Included support to recognize correctly the temperatures and RPM values when + in some weird cases, the FAN and CPU labels (in the lm_sensors output) share + the same name. + (thanks to Luca Ferrario, luca AT ferrario.net) +- Fixed a duplication in the Monitorix iptables rules during a restart. +- Added support for systems with device interrupt numbers greater than 255. +- Added support for openSuSE/SLES Linux distribution. + (thanks to Alessandro Soraruf, soraruf AT ntd.homelinux.org) + + +1.2.3 - 14-Jan-2009 +==================== +- Fixed the way how Monitorix creates the iptables rules. Now it uses the + parameter -I instead the -A in order to insert those rules in the top of + each chain so the data get recorded. + (thanks to Andrei Ioachim, andrei AT inteligis.com) +- Added support for the Postfix MTA in the SMTP counter of the Network Services + Demand graph. + (thanks to Andrei Ioachim, andrei AT inteligis.com) +- Fixed a typo in the declaration of $HTDOCS in the install.sh that only + affected to Gentoo installations. + (thanks to Carlos Perez, cpa.admin AT gmail.com) +- Removed the dependence of the 'lockfile' command in the init-script. + (suggested by Carlos Perez, cpa.admin AT gmail.com) +- Fixed to detect and show better the interrupt names. +- Added a minimal support for interrupt numbers bigger than 255. This minimal + support will let you see the names of those interrupts that have those big + numbers but their activity will rest still void. + (thanks to Brian Lopeman, brian.lopeman AT ctrh.org) +- Fixed a missing '127.0.0.1' in the URL of the graph images when + 'monitorix.cgi' is called from the command line. + (thanks to David Tiberio, dave AT cheapbooks.com) + + +1.2.2 - 20-Nov-2008 +==================== +- Fixed a missing '/' when removing /var/www/monitorix in the un_install.sh + script. + (thanks to Tamas Marki, tamas AT gnsdm.com) +- Fixed to really accept more than three network devices. There were some parts + that were not correctly upgraded to five. + (thanks to Milos Prudek, prudek AT bvx.cz) +- Added the parameter -w during the hddtemp call just to make sure that it will + awaken the disk (if needed). +- Removed the .sh extension and the she-bang in the crond script for all Linux + distributions, although only in the Debian based ones people experienced + problems. +- Added a new configuration option to disable the crond mail related to + Monitorix errors. + (suggested by Detlef Neubauer, detlef.neubauer AT wzrz.de) +- Fixed to include the "Linux-Generic" as a supported OSTYPE. +- Fixed to include the monthly report files for the Italian language in the RPM + package. +- Removed the htmlentity of the ampersand character introduced in the previous + version, as the last RRDtool version seems not complaining anymore. +- Improved the way how the root filesystem device is detected including support + for the partitions with two digits like /dev/sda10. + (suggested by Dimitri Yioulos, dyioulos AT firstbhph.com) + + +1.2.1 - 01-Oct-2008 +==================== +- Added support for the new RRDtool 1.3 version. +- Fixed the alignment of the MB & CPU temperatures graph legend. +- Forced the font type to 'Mono' for the RRDtool 1.3 version. +- Fixed one identifier to count better the total messages sent/received in + /var/log/maillog. +- Added support for some virtualized systems where the rootfs device name does + not appears in /proc/diskstats and the only way to collect the i/o values is + using the partition device name. + (thanks to Travis Wu, twu AT capitalsystems.com) +- Added support for Linux software RAID devices of the form /dev/md/*. + (thanks to an anonymous IRC user called 'emilio') +- Added Italian language support in the monthly traffic report. + (thanks to Luca Ferrario, luca AT ferrario.net) +- Fixed the ampersand character to be an entity to avoid complaining messages + of Pango in the RRDtool 1.3 version. +- Included the "Linux-Generic" OSTYPE key that for a strange reason it was + missing. +- Fixed in the cover web page to only include the graphs that the system can + really offer. That will avoid to see more ethernets graphs than the number + of real ethernet devices and the same for the number of processors. + + +1.2.0 - 02-Apr-2008 +==================== +- Added support for systems based on LVM structure on top of a CCISS RAID of + disk drives. + (thanks to Bob McClure, Jr., bob AT bobcatos.com) +- Removed the full path of the 'pvs' command as it complicates the portability + of Monitorix to other Linux distributions. + (thanks to Eric, teknologist AT gmail.com) +- Added the "no warnings" pragma to temporarily block warnings while calling + the 'sensors' command. +- Fixed a bug introduced in the last version that prevented to see the interrupt + names on systems with 2.4 Linux kernels. +- Fixed the graph of disk temperatures in order to preserve the page layout + when there's no defined any disk device in the HDDTEMP_LIST array. + (thanks to Eric, teknologist AT gmail.com) +- Fixed to tolerate if @HDDTEMP_LIST was badly defined with just a void entry + instead of no entries at all. That's if someone defined incorrectly the array + as @HDDTEMP_LIST = ""; instead of simply as @HDDTEMP_LIST; + (thanks to Eric, teknologist AT gmail.com) +- Removed the error messages when it has been defined in /etc/monitorix.conf a + network interface that it doesn't exist in the system. +- Fixed the error message "Use of uninitialized value in string eq at + /var/www/cgi-bin/monitorix.cgi line 454." that appeared in the Apache error + logs when using Multihost feature. + + +1.1.2 - 25-Feb-2008 +==================== +- Added the execution of the "pvs -a" command each time Monitorix is restarted, + just to make sure to remove a strange message about "Medium not found" + appeared on fresh CentOS 5 installations using LVM. +- Converted automatically into a link the URL that appears in the bottom of + each graph (if enabled by $MULTIHOST_FOOTER) in the Multihost mode. +- Fixed to put the zero character instead of NULL when there's no value, in the + monthly file of traffic during the daily collecting of counters. +- Fixed a bug in the interrupt names that removed its first character affecting + only (mostly old) machines with "local-APIC-edge" support. + + +1.1.1 - 16-Nov-2007 +==================== +- Fixed a stupid bug that prevented showing the graphs of network ports. + + +1.1.0 - 15-Nov-2007 +==================== +- Added support for Gentoo Linux distribution. + (thanks to Matej Povazaj, ybdaba AT gmail.com) +- Added support for Slackware Linux distribution. + (thanks to Bogdan Radulescu, from http://nimblex.net> +- Changed the way how is the data collected in the Kernel Usage graph. From now + on, this graph will show its data in a more accurated way than before. People + can continue using the Real and Stacked modes though. + (thanks to Christian Meusel, christian.meusel AT inf.tu-dresden.de) +- Definitely fixed (I really hope so) a persistent bug during the numeric + extraction of the alpha numeric string of the lm_sensors temperatures. +- Fixed support for HP ML310 ProLiant server in the motherboard temperatures + graph. +- Changed the main page form method from POST to GET in order to be able to + remove the old /cgi-bin/monitorix.cgi and call localhost.cgi directly. + So now on, the localhost.cgi is renamed as monitorix.cgi and it's placed in + the same place where it was the old one, removing the /cgi-bin/monitorix + directory as it will not longer be used. +- Fixed to show the graph when using multihost feature and select only the + Context Switches graph. +- Improved how are showed the images when using multihost feature selecting + only individual hosts. Now they are bigger. + + +1.0.1 - 03-Oct-2007 +==================== +- Fixed some annoying messages like "Argument "+46M-BM-0C" isn't numeric in int + at /usr/bin/monitorix.pl line > 2710, line 13.". Now it extracts + correctly numbers from an alpha numeric string. + (thanks to Russell Morris, rmorris AT rkmorris.us) +- Changed from area-based to line-based the HP IPL temperature graphs in order + to follow the same aspect than the new LM-Sensors graph. +- Added a permanent "lower-limit=0" in the following graphs: Context Switches, + LM-Sensors, Network Packet Traffic and Network Error Traffic. +- Fixed the alignment of the legend in the FAN speeds graph on systems still + using the old RRDtool branch version 1.0. + + +1.0.0 - 04-Sep-2007 +==================== +- Added a new graph to see the temperatures of the system motherboard, CPUs, + fan speeds and hard disk drives using lm_sensors and the hddtemp tool. Such + graph is disabled by default since there are still a lot of motherboards with + unsupported sensors out there. This new graph can be combined with the HP + specific temperatures graph. +- Fixed some adjustments in the temperatures collector in newer HP ProLiant + servers with newer IML. +- Added the ability to select the percentages layout in the Kernel Usage + statistics. The possible options are (R)eal or (S)tacked. + (suggested by Andrzej Pokrywko, Andrzej.Pokrywko AT onet.pl) +- Fixed a bug that prevented to display correctly the interrupt names on newer + systems that use PCI-MSI instead of IO-APIC. +- Added the ability to change the refresh rate value in the statistics web + page. The default value remains unchanged to 150 seconds. +- Added some adjustments in the Monitorix init script. +- Extended the environment variable PATH to cover more root directories. +- Changed the default NET_RIGID from 2 to 0. +- Changed the default network configuration from two interfaces to only one, as + it seems the most of people have only one network interface installed. +- Removed some "Use of uninitialized value ..." annoying messages in the Apache + error_log. + + +0.9.2 - 12-Jun-2007 +==================== +- Special Debian contribution. + + Added support for Debian distribution. + + Added the missing "monitorixico.png" file during the install process using + the install.sh shell-script. + (thanks to Uwe Heidrich, uweheidrich AT hotmail.com) +- Added German language support in the monthly report. + (thanks to Uwe Heidrich, uweheidrich AT hotmail.com) +- Added support for systems using Linux RAID systems under LVM. +- Fixed in the localhost.cgi and in monitorix.pl files to not include a second + configuration file if the first one already exists. +- Fixed the graphs legend lines adding blank lines in order to have a better + formatting. That only affected those who have RRDtool version above 1.2.13. +- Added the Zoom feature that, when enabled, it will permits to see a larger + picture just clicking inside any graph image. + (suggested by Dimitri Yioulos, dyioulos AT firstbhph.com) +- Removed the degree symbol in all the temperature graphs. +- Some little code cleanup. + + +0.9.1 - 09-Jan-2007 +==================== +- Fixed some annoying cron messages about uninitialized value during an addition + and a multiplication, only on 2.4 kernels. +- Fixed the line and area colors in the kernel-related new graphs. + + +0.9.0 - 03-Jan-2007 +==================== +- Fixed the background color of the graphs in Multihost feature. +- Added a lot of new colors to cover as many hardware interrupts as they exist. +- Added the Monitorix shortcut icon. +- Fixed a bad closing in the global tag. +- Fixed and optimized the start routine in the init script. +- Added a new composed-graph to see the Linux kernel usage per processor. The + graph will be divided by three parts (as always) only using, right now, the + biggest and the first one of the last two. The graph will show the global + percentages of total user time, nice time, system time, idle time and io-wait + time and separately, the number of context switches. Finally if the system + has multiprocessors there will be an individual graph per processor showing + the percentages of its CPU times (up to 8 processors). + (suggested by Michael Berger, MBerger AT scrippsops.com) +- Added a configuration switch (Y/N) per graph to enable or disable its + processing. This will help specially on embedded systems (where there is not + much disk space) to monitorize only what it is really needed. +- IMPORTANT NOTICE: The configuration file (/etc/monitorix.conf) has been + extended with important changes. + + +0.8.3 - 16-Oct-2006 +==================== +- Added the word "easier" to the Monitorix slogan. +- Added support for CCISS Compaq RAID driver under 2.6 Linux kernels. +- Changed the color for the first mounted filesystem in the disk usage, now is + darker. +- Changed all the white colors to gray in order to be more visible when using + the white theme. +- Changed the Fax color (from white to orange). +- Adjusted three colors in the interrupt activity graphs: from gray to orange, + from black to dark-gray and from white to light-gray. +- Changed the color of the running processes (from dark blue to red). +- Changed the HTML font from the Arial,Helvetica to Verdana,Tahoma, and switched + to lowercase all the HTML tags. +- Fixed a problem when finding the root disk on LVM systems with multiple disks + on the same logical volume. + (thanks to Bon, bon AT bugstudio.net) +- Consolidated to only one internal function all temperature graphs concerning + to the Hewlett-Packard server models. +- Fixed a broken image in the third temperature graph on some Hewlett-Packard + server models. +- Added support for up to 255 hardware interrupts to take advantatge of the + APIC feature in newer Linux systems. The "int.rrd" database will be upgraded + automatically. +- Because of the new support for so many interrupts, the interrupt graphs no + longer displays the unused ones. +- Added support for up to 5 NICs. The "net.rrd" database will be upgraded + automatically. + (suggested by Mike Harris, MikeDawg AT addictz.org) +- Removed the use of the generation number from the HP ProLiant servers, because + there are no differencies In the number of processors between the current + generations. Now the server names are changed from ML350G3 to simply ML350. + + +0.8.2 - 04-Jul-2006 +==================== +- Changed from dark-gray to orange the color of the last mount point in the + disk usage graph. +- Added error handling during the creation of the RRDs database files. +- Fixed a graph creation error when trying to view the PC LANs on systems with + RRDtool v1.2+. +- Fixed a graph creation error during the monthly report creation on systems + with RRDtool v1.2+. +- Fixed to take care about the color selected when creating the monthly report + graphs. +- Fixed a typo when cutting the last digit of $root_disk. + (thanks to Christoph Fritsche, Christoph.Fritsche AT fh-telekom-leipzig.de) +- Added the new parameter "silent=imagetag" which among of the image + generation it will return the HTML tag for the specified image. +- Fixed the annoying old behaviour of the Multihost feature that obligates to + reload the page two times every time you want to see the most up to date + remote server graphs. +- Some cosmetic changes. + + +0.8.1 - 17-May-2006 +==================== +- Fixed problems while creating the ip counters when the network port variables + $PORT01, $PORT02, ... are removed or not defined in the configuration file. +- Added better support for Linux Software RAID devices (/dev/md0, /dev/md1, ...). +- Added specific colored logo images for black and white themes. +- Optimized the way how are used the chomp() functions, using now multiple + arguments. +- Optimized all the code that was using system commands to collect information. +- Dramatically reduced the CPU load average on most systems specially on slow or + old systems. As an example of that, a Pentium at 133Mhz sees reduced to 50% + its CPU load. +- More code cleaning. + + +0.8.0 - 27-Mar-2006 +==================== +- Almost complete support for FreeBSD based systems. + (thanks to Roger "Rocky" Vetterberg, roger AT vetterberg.com) + (thanks to the twenty4help, http://www.twenty4help.com) +- Code prepared to be more easily portable to other UNIX/Linux systems. +- Changed the location of the configuration file to /etc/monitorix.conf. +- Fixed a "grep" condition problem with LVM based systems not using LVM. + (thanks to Yazhir, admin AT pazeng.co.il) +- Fixed to escape more possible colons on interrupt device names. +- Fixed graph font size for RRDtool versions 1.2+. +- Better support for RRDtool version 1.2. +- Fixed the counter of the amount of Samba locked files. +- Better monitorization in the detection of VirusMail (requires MailScanner). +- Improved the Active Processes graph, now includes the sleeping and running + processes in order to know better the amount of concurrent processes the + server has. +- Now the cron file is automatically created taking care the OS usual paths. +- Removed the default names for the unused interrupt devices. Now all the unused + interrupts will be marked as "unused". +- Fixed the order of collected data in disk activity graphs. +- More code cleaning and removed some unused variables. + + +0.7.14 - 17-Jan-2006 +==================== +- Fixed to be more accurate the way how are detected the ports that are down. +- Removing annoying cron messages and added again the locking mechanism. + + +0.7.13 - 16-Jan-2006 +==================== +- Added an automatic space-padding control to the MNT_LIST mount points names. +- Fixed "val" and "mode" declarations and added a hint into README file for + users coming from other Linux distributions. + (thanks to Christoph Fritsche, s03315 AT fh-telekom-leipzig.de ) +- Really added the parameter "-P" in the "df" lines. In the previous version it + was only commented in the ChangeLog. +- Added a new file in the /etc/httpd/conf.d/ which will make the alias + "/monitorix", and will facilitate the installation with different html root + directories. +- Added an initial support for LVM (Logical Volume Manager) based systems. +- Added a warning indicator (changing the color background to red) on the 12 + port graphs for each selected port if it seems to be down. +- Removed temporaly the locked mechanism introduced in the previous version + because it produces annoying cron messages everyday at midnight. +- Some little code cleaning. + + +0.7.12 - 07-Nov-2005 +==================== +- Fixed the stat() function that prevented to collect Samba and NetAtalk data. +- Escape colons in Interrupt names (INT_NAME) for rrdtool 1.2 branch versions. + (thanks to Marcos Andre, foca AT siagri.com.br) +- Added the parameter "-P" in order to prevent multi-line output from "df". + (thanks to Rene Kapeller, rene.kapeller AT psi.ch) +- Added a locking mechanism to prevent concurrent executions of Monitorix, that + will be useful on very high loaded servers. + (thanks to Rene Kapeller, rene.kapeller AT psi.ch) + + +0.7.11 - 06-Oct-2005 +==================== +- Now the POP3 section is looking for pop3 string (not pop-3) in log entries. +- It handles possible DNS no resolution for defined PC LANs. +- Added English language support for the monthly reports. +- Removed the PC_DS list. Monitorix only will use PC_LIST and PC_IP if needed. +- Remove the hard-coded command paths in order to be more distro compatible. +- Added some checks in order to warn if some directories or files can't be read. +- Fix to escape only colons for rrdtool 1.2 branch versions. + + +0.7.10 - 26-Sep-2005 +==================== +- Reduced the size of the Monitorix logo in the startup screen. +- Finally fixed the problem with disk i/o on 2.6 kernels. +- Fixed some incompatibilities in order to support RRDtool v1.2. + (thanks to Alex Shiffer, refys AT zelacom.com) +- Removed MONITORIX_VER variable from the configuration file. + + +0.7.9 - 12-Sep-2005 +==================== +- Some cleanups in the Configuration.help file. +- Remove annoying samba messages in cron when samba is not running. +- Fixed bug when collecting disk i/o on kernels 2.6 (/proc/diskstats). + (thanks to Alf Tanner, alf.tanner AT gmail.com) + + +0.7.8 - 11-Sep-2005 +==================== +- Initial public release. + diff --git a/README b/README new file mode 100644 index 0000000..93ae350 --- /dev/null +++ b/README @@ -0,0 +1,170 @@ +INTRODUCTION +=============================================================================== +Monitorix is a free, open source, lightweight system monitoring tool designed +to monitor as many services and system resources as possible. It has been +created to be used under production UNIX/Linux servers, but due to its +simplicity and small size may also be used to monitor embedded devices as +well. + +It consists mainly of two programs: a collector, called monitorix, which +is a Perl daemon that is started automatically like any other system service, +and a CGI script called monitorix.cgi. + +Every time 'monitorix' is started it reads the configuration file from the path +specified in the command line (using the -c option), and once checked, it +creates the 'index.html' file that will act as the Monitorix main page. + +It also creates a file called '$BASE_DIR/cgi-bin/monitorix.conf.path' that +includes the absolute path of the configuration file. This file will be read +by 'monitorix.cgi' to determine the exact location of the configuration file. +If for any reason it is unable to locate this file, Monitorix will try two +alternative locations: '/etc/monitorix.conf' and +'/usr/local/etc/monitorix.conf'. + + +HISTORY +=============================================================================== +All of its development was initially created for monitoring Red Hat, Fedora and +CentOS Linux systems, so this project was made keeping in mind these type of +distributions. Today it runs on different GNU/Linux distributions and even in +other UNIX systems, like FreeBSD, OpenBSD and NetBSD. + +On March 2006, Monitorix included minimal support to run on FreeBSD systems. My +special thanks to twenty4help Knowledge Service and to Roger "Rocky" Vetterberg +for their support and help, and for being good friends during the porting +process. + +Since the release of 1.3.2 though, Monitorix has almost full support for +FreeBSD. My special thanks to Pavlin Vatev who generously offered his support +during all of the process. + +With the release 2.0.0 Monitorix suffered a complete rewrite, including new +features and graphs, cleaned up all the code, updated and enhanced a number of +aspects in some graphs, and fixed a lot of bugs. The most important change was +that it no longer required 'crond' to work, instead Monitorix became a complete +standalone Perl daemon being started and stopped like any other system service. + +Since the release 2.2.0 Monitorix includes support for OpenBSD systems. My +special thanks to Devio.us team for giving me a free shell account where to put +hands to work. + +Since the release 2.6.0 Monitorix includes support for NetBSD systems. + + +IMPORTANT NOTE +=============================================================================== +The configuration file is a Perl file where values are directly assigned to +variables that Monitorix uses during normal operation; you should take care to +conform to basic Perl syntax. + +Please, see the monitorix.conf(5) and monitorix(8) man pages. + + +REQUIREMENTS +=============================================================================== +Monitorix requires some others packages to be installed that your GNU/Linux +distribution may or may not have: + +- A CGI capable Web server (Apache, Nginx, lighttpd, etc.) +- Perl +- Perl-CGI +- Perl-MailTools +- Perl-MIME-Lite +- Perl-libwww +- Perl-DBI +- Perl-XML-Simple +- RRDtool and its Perl bindings (perl-rrdtool or rrdtool-perl) + +You can download RRDtool from different places: + http://pkgs.repoforge.org/rrdtool/ + http://oss.oetiker.ch/rrdtool/ + + +INSTALLATION +=============================================================================== +The file tree for the Monitorix application is: + +File Recommended location Description +------------------------------------------------------------------------------- +monitorix /usr/bin/ main program (daemon) +monitorix.cgi $BASE_DIR/cgi-bin/ CGI (viewer) +monitorix.conf /etc/ configuration file +Changes /usr/share/doc/ changes log file +COPYING /usr/share/doc/ license +logo_bot.png $BASE_DIR bottom logo +logo_top.png $BASE_DIR top logo +monitorixico.png $BASE_DIR favicon +monitorix-alert.sh /usr/share/doc/ alert example script +monitorix-apache.conf /etc/httpd/conf.d/ apache configuration +monitorix.init /etc/init.d/ redhat init script +monitorix-deb.init /etc/init.d/ debian init script +monitorix.logrotate /etc/logrotate.d/ logrotate script +monitorix.spec /usr/share/doc/ RPM spec file +monitorix.sysconfig /etc/sysconfig/ pre-run config file +monitorix.lighttpd /etc/lighttpd/ lighttpd configuration +README /usr/share/doc/ documentation +README.FreeBSD /usr/share/doc/ documentation +README.nginx /usr/share/doc/ documentation +README.OpenBSD /usr/share/doc/ documentation +README.NetBSD /usr/share/doc/ documentation +man/man5/monitorix.conf.5 /usr/share/man/man5/ monitorix.conf manpage +man/man8/monitorix.8 /usr/share/man/man8/ monitorix manpage +reports/*.html $BASE_LIB/reports/ monthly reports i18n +reports/send_reports $BASE_LIB/reports/ script to send reports + + +Once succesfully installed, please take a look into the configuration file to +setup the options according your system and enable or disable graphs. + +Finally start Monitorix using the system init script: + +# service monitorix start + +or with: + +# /etc/init.d/monitorix start + +At this point, Monitorix will start gathering the system information based on +the configuration setup in 'monitorix.conf' file, and after some minutes, you +should be able to see the results from your favorite browser pointing at: + +http://localhost/monitorix/ +(don't forget to (re)start your webserver) + + +AUTHORS +=============================================================================== +Monitorix is written and actively maintained by Jordi Sanfeliu. + +Many people further contributed by reporting problems, suggesting various +improvements, sharing ideas or submitting actual code. Since the list might be +incomplete, please see the 'Changes' file for a detailed description of all the +contributions. +My special thanks to all of them! + + +CONTACT +=============================================================================== +In case of help, bugs, ideas or suggestions please contact using any of the +following ways: + +- IRC at freenode: #monitorix +- Mailing List: https://lists.sourceforge.net/lists/listinfo/monitorix-general +- Direct Email: Jordi Sanfeliu + + +DONATIONS +=============================================================================== +If you or your company make regular use of this software, please consider +making a donation to the author to support open source effort. +Many thanks for any donation! + + +LICENSE AND COPYRIGHT +=============================================================================== +Monitorix is distributed under the terms of the GNU General Public License. +See the included file "COPYING". + +Copyright (C) 2005-2012 Jordi Sanfeliu. +http://www.monitorix.org + diff --git a/README.FreeBSD b/README.FreeBSD new file mode 100644 index 0000000..167dc51 --- /dev/null +++ b/README.FreeBSD @@ -0,0 +1,18 @@ +Notes to read after installation of Monitorix 2.4+ in FreeBSD systems +=============================================================================== +Please take some time adjusting the options in the monitorix.conf file. +See the monitorix.conf(5) man page for a detailed help of each configuration +option. + +Make sure that the default ipfw(8) rule numbers defined in the monitorix.conf +file doesn't conflict with any other rule number in your firewall: + - $PORT_RULE = "24000"; + - $NGINX_RULE = "24100"; + +This is the list of things that still need attention: + - [PCLAN] - PC LAN Internet activity is not supported yet. Help needed! + - [SERV] - Some services may not work. + - [HPTEMP] - HP Temperatures may not work because of the lack of HP software. + - [NFSS] - NFS server is not supported yet. + - [NFSC] - NFS client is not supported yet. + diff --git a/README.NetBSD b/README.NetBSD new file mode 100644 index 0000000..a0fa97d --- /dev/null +++ b/README.NetBSD @@ -0,0 +1,19 @@ +Notes to read after installation of Monitorix 2.6+ in NetBSD systems +=============================================================================== +Please take some time adjusting the options in the monitorix.conf file. +See the monitorix.conf(5) man page for a detailed help of each configuration +option. + +This is the list of things that still need attention: + - IP filter not supported yet, hence some network activity graphs won't work. + - File usage in 'VFS usage' graph doesn't work. + - [PROC] - Per processor kernel usage graph is not available because the + command 'sysctl kern.cp_time2' doesn't work yet. + - [PORT] - Network port activity not supported yet. + - [PCLAN] - PC LAN Internet activity is not supported yet. Help needed! + - [SERV] - Some services may not work. + - [HPTEMP] - HP Temperatures may not work because of the lack of HP software. + - [NFSS] - NFS server is not supported yet. + - [NFSC] - NFS client is not supported yet. + - [INT] - Device interrupt activity not supported yet. + diff --git a/README.OpenBSD b/README.OpenBSD new file mode 100644 index 0000000..da135f5 --- /dev/null +++ b/README.OpenBSD @@ -0,0 +1,20 @@ +Notes to read after installation of Monitorix 2.4+ in FreeBSD systems +=============================================================================== +Please take some time adjusting the options in the monitorix.conf file. +See the monitorix.conf(5) man page for a detailed help of each configuration +option. + +Make sure that the default ipfw(8) rule numbers defined in the monitorix.conf +file doesn't conflict with any other rule number in your firewall: + - $PORT_RULE = "24000"; + - $NGINX_RULE = "24100"; + +This is the list of things that still need attention: + - [PROC] - Per processor kernel usage graph is not available because the + command 'sysctl kern.cp_time2' doesn't work yet. + - [PCLAN] - PC LAN Internet activity is not supported yet. Help needed! + - [SERV] - Some services may not work. + - [HPTEMP] - HP Temperatures may not work because of the lack of HP software. + - [NFSS] - NFS server is not supported yet. + - [NFSC] - NFS client is not supported yet. + diff --git a/README.nginx b/README.nginx new file mode 100644 index 0000000..7b9a1d9 --- /dev/null +++ b/README.nginx @@ -0,0 +1,31 @@ +NOTES FOR THOSE WHO WANT TO MONITOR 'nginx' WEB SERVER +=============================================================================== +Since the 1.3.0 version and thanks to Aleksandr Miroshnychenko +(al.miroshnychenko AT gmail.com) it is possible to enable the monitorization +of the Nginx web server (http://nginx.net/). + +Here are the steps: + +1) Edit the 'monitorix.conf' file to enable the 'nginx' monitorization and set + the correct network port where Nginx is listening on: + our %GRAPH_ENABLE = ( + [...] + "nginx" => "Y", + [...] + + our $NGINX_PORT = "80"; + +2) Make sure 'nginx' is compiled with the flag: + --with-http_stub_status_module + +3) Edit the 'nginx.conf' file and add or uncomment in the server section the + following: + location /nginx_status { + stub_status on; + access_log off; + allow 127.0.0.1; + deny all; + } + +4) Restart Nginx and Monitorix. + diff --git a/docs/monitorix-alert.sh b/docs/monitorix-alert.sh new file mode 100755 index 0000000..e62946f --- /dev/null +++ b/docs/monitorix-alert.sh @@ -0,0 +1,29 @@ +#!/bin/sh +# +# Example script used to execute an alert action. +# +# - in CPU alerts the current value is the last 15min load average +# - in FS alerts the current value is the root filesystem usage (%) +# + +if [ $# != 3 ] ; then + echo "$0: Wrong number of parameters." + exit 1 +fi + +ALERT_TIMEINTVL=$1 +ALERT_THRESHOLD=$2 +current_value=$3 + +( +cat << EOF +Message from hostname '$HOSTNAME' + +This system is reaching/exceeding the defined $ALERT_THRESHOLD threshold during the last $ALERT_TIMEINTVL seconds. + +The current value is: $current_value + +Please take proper actions to correct this situation. +EOF +) | mail -s "WARNING: Monitorix alert!" root + diff --git a/docs/monitorix-apache.conf b/docs/monitorix-apache.conf new file mode 100644 index 0000000..93247e5 --- /dev/null +++ b/docs/monitorix-apache.conf @@ -0,0 +1,32 @@ +# +# Monitorix is a lightweight system monitoring tool +# + +Alias /monitorix /usr/share/monitorix +ScriptAlias /monitorix-cgi /usr/share/monitorix/cgi-bin + + + DirectoryIndex monitorix.cgi + Options ExecCGI + Order Deny,Allow + Deny from all + Allow from 127.0.0.1 + + +# Apache rules to restrict access to Monitorix: +# Don't forget to add in .htpasswd with the 'htpasswd' command. +# +# +# Options Indexes Includes FollowSymLinks +# Order Deny,Allow +# Deny from All +# Allow from 127.0.0.1 +# AllowOverride None +# AuthUserFile /etc/httpd/conf/.htpasswd +# AuthGroupFile /dev/null +# AuthName "Monitorix: Restricted access, sorry." +# AuthType Basic +# Require user +# Satisfy Any +# + diff --git a/docs/monitorix-deb.init b/docs/monitorix-deb.init new file mode 100755 index 0000000..a120af5 --- /dev/null +++ b/docs/monitorix-deb.init @@ -0,0 +1,88 @@ +#!/bin/sh + +### BEGIN INIT INFO +# Provides: monitorix +# Required-Start: +# Required-Stop: +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Start Monitorix daemon +### END INIT INFO + +# PATH should only include /usr/* if it runs after the mountnfs.sh script +PATH=/sbin:/usr/sbin:/bin:/usr/bin + +DESC="Monitorix" +NAME="monitorix" +CONF="/etc/monitorix.conf" +DAEMON="/usr/bin/$NAME" +PIDFILE="/var/run/$NAME.pid" +LOCKFILE="/var/lock/$NAME" +SCRIPTNAME="/etc/init.d/$NAME" +DAEMON_ARGS="-c $CONF -p $PIDFILE" + + +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 5 + +# Read configuration variable file if it is present +[ -r /etc/default/$NAME ] && . /etc/default/$NAME + +# Load the VERBOSE setting and other rcS variables +. /lib/init/vars.sh + +# Define LSB log_* functions. +# Depend on lsb-base (>= 3.0-6) to ensure that this file is present. +. /lib/lsb/init-functions + +lock_monitorix() { + if [ -x /usr/bin/lockfile-create ]; then + lockfile-create $LOCKFILE + lockfile-touch $LOCKFILE & + LOCKTOUCHPID="$!" + fi +} + +unlock_monitorix() { + if [ -x /usr/bin/lockfile-create ] ; then + kill $LOCKTOUCHPID + lockfile-remove $LOCKFILE + fi +} + +case $1 in + start) + [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC $NAME" + lock_monitorix + start-stop-daemon --start --quiet --oknodo --pidfile $PIDFILE --startas $DAEMON -- -p $PIDFILE $DAEMON_ARGS + status=$? + unlock_monitorix + log_end_msg $status + ;; + stop) + [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC $NAME" + start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE + log_end_msg $? + rm -f $PIDFILE + ;; + restart|force-reload) + $0 stop && sleep 2 && $0 start + ;; + try-restart) + if $0 status >/dev/null; then + $0 restart + else + exit 0 + fi + ;; + reload) + exit 3 + ;; + status) + status_of_proc $DAEMON "$DESC" + ;; + *) + echo "Usage: $0 {start|stop|restart|try-restart|force-reload|status}" + exit 2 + ;; +esac diff --git a/docs/monitorix-lighttpd.conf b/docs/monitorix-lighttpd.conf new file mode 100644 index 0000000..b0f9b24 --- /dev/null +++ b/docs/monitorix-lighttpd.conf @@ -0,0 +1,4 @@ +$HTTP["host"] =~ "your\.monitorix\.vhost$" { + server.document-root = "/var/www/localhost/htdocs/monitorix" + alias.url = ( "/cgi-bin" => "/var/www/localhost/cgi-bin/" ) +} diff --git a/docs/monitorix.init b/docs/monitorix.init new file mode 100755 index 0000000..8ef13ff --- /dev/null +++ b/docs/monitorix.init @@ -0,0 +1,87 @@ +#!/bin/bash +# +# /etc/rc.d/init.d/monitorix +# +# Starts the Monitorix daemon +# +# chkconfig: 2345 99 10 +# description: Monitorix is a lightweight system monitoring tool +# processname: monitorix +# config: /etc/monitorix.conf +# pidfile: /var/run/monitorix.pid + +### BEGIN INIT INFO +# Provides: monitorix +# Required-Start: $local_fs +# Required-Stop: $local_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Start up the Monitorix daemon +# Description: Monitorix is a free, open source, lightweight system +# monitoring tool designed to monitor as many services and +# system resources as possible. +### END INIT INFO + +# Source function library +. /etc/init.d/functions + +if [ -f /etc/sysconfig/monitorix -a $UID -eq 0 ]; then + . /etc/sysconfig/monitorix +fi + +RETVAL=0 +PROG="monitorix" +DAEMON="/usr/bin/monitorix" +PIDFILE="/var/run/monitorix.pid" +CONF="/etc/monitorix.conf" + +start() { + if [ ! -f /var/lock/subsys/$PROG ] ; then + echo -n $"Starting $PROG: " + daemon $DAEMON -c $CONF -p $PIDFILE $OPTIONS && success || failure + RETVAL=$? + if [ $RETVAL -eq 0 ] ; then + touch /var/lock/subsys/$PROG + echo + fi + fi +} + +stop() { + echo -n $"Stopping $PROG: " + killproc $PROG + RETVAL=$? + rm -f /var/lock/subsys/$PROG + rm -f $PIDFILE + echo +} + +restart() { + stop + start +} + +case "$1" in + start) + start + ;; + stop) + stop + ;; + restart) + restart + ;; + condrestart) + if [ -f /var/lock/subsys/$PROG ] ; then + restart + fi + ;; + status) + status $PROG + ;; + *) + echo $"Usage: $0 {start|stop|restart|condrestart|status}" + exit 1 +esac + +exit $RETVAL diff --git a/docs/monitorix.logrotate b/docs/monitorix.logrotate new file mode 100644 index 0000000..d39e36c --- /dev/null +++ b/docs/monitorix.logrotate @@ -0,0 +1,7 @@ +/var/log/monitorix { + nocompress + missingok + postrotate + /bin/kill -HUP `cat /var/run/monitorix.pid 2>/dev/null` 2> /dev/null || true + endscript +} diff --git a/docs/monitorix.spec b/docs/monitorix.spec new file mode 100644 index 0000000..0ec6699 --- /dev/null +++ b/docs/monitorix.spec @@ -0,0 +1,96 @@ +# rpm spec for Monitorix +# + +Summary: Monitorix is a system monitoring tool +Name: monitorix +Version: 2.6.0 +Release: 1%{?dist} +License: GPL +Group: Applications/System +URL: http://www.monitorix.org +Packager: Jordi Sanfeliu + +Source: %{name}-%{version}.tar.gz +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root +BuildArch: noarch + +Requires: rrdtool +Requires: perl +Requires: perl-libwww-perl +Requires: perl-MailTools +Requires: perl-MIME-Lite +Requires: perl-DBI +Requires: perl-XML-Simple + +%description +Monitorix is a free, open source, lightweight system monitoring tool designed +to monitor as many services and system resources as possible. It has been +created to be used under production UNIX/Linux servers, but due to its +simplicity and small size may also be used on embedded devices as well. + +%prep +%setup + +%build + +%install +rm -rf %{buildroot} +mkdir -p %{buildroot}%{_initrddir} +install -m 0755 docs/monitorix.init %{buildroot}%{_initrddir}/monitorix +mkdir -p %{buildroot}%{_sysconfdir}/httpd/conf.d +install -m 0644 docs/monitorix-apache.conf %{buildroot}%{_sysconfdir}/httpd/conf.d/monitorix.conf +mkdir -p %{buildroot}%{_sysconfdir}/logrotate.d +install -m 0644 docs/monitorix.logrotate %{buildroot}%{_sysconfdir}/logrotate.d/monitorix +mkdir -p %{buildroot}%{_sysconfdir}/sysconfig +install -m 0644 docs/monitorix.sysconfig %{buildroot}%{_sysconfdir}/sysconfig/monitorix +mkdir -p %{buildroot}%{_sysconfdir} +install -m 0644 monitorix.conf %{buildroot}%{_sysconfdir}/monitorix.conf +mkdir -p %{buildroot}%{_bindir} +install -m 0755 monitorix %{buildroot}%{_bindir} +mkdir -p %{buildroot}%{_datadir}/monitorix +install -m 0644 logo_top.png %{buildroot}%{_datadir}/monitorix +install -m 0644 logo_bot.png %{buildroot}%{_datadir}/monitorix +install -m 0644 monitorixico.png %{buildroot}%{_datadir}/monitorix +mkdir -p %{buildroot}%{_datadir}/monitorix/imgs +mkdir -p %{buildroot}%{_datadir}/monitorix/cgi-bin +install -m 0755 monitorix.cgi %{buildroot}%{_datadir}/monitorix/cgi-bin +mkdir -p %{buildroot}%{_localstatedir}/lib/monitorix/reports +install -m 0644 reports/*.html %{buildroot}%{_localstatedir}/lib/monitorix/reports +install -m 0755 reports/send_reports %{buildroot}%{_localstatedir}/lib/monitorix/reports +mkdir -p %{buildroot}%{_localstatedir}/lib/monitorix/usage +mkdir -p %{buildroot}%{_mandir}/man5 +mkdir -p %{buildroot}%{_mandir}/man8 +install -m 0644 man/man5/monitorix.conf.5 %{buildroot}%{_mandir}/man5 +install -m 0644 man/man8/monitorix.8 %{buildroot}%{_mandir}/man8 + +%clean +rm -rf %{buildroot} + +%post +/sbin/chkconfig --add monitorix + +%files +%defattr(-, root, root) +%{_initrddir}/monitorix +%config(noreplace) %{_sysconfdir}/httpd/conf.d/monitorix.conf +%config(noreplace) %{_sysconfdir}/logrotate.d/monitorix +%config(noreplace) %{_sysconfdir}/sysconfig/monitorix +%config(noreplace) %{_sysconfdir}/monitorix.conf +%{_bindir}/monitorix +%{_datadir}/monitorix/logo_top.png +%{_datadir}/monitorix/logo_bot.png +%{_datadir}/monitorix/monitorixico.png +%{_datadir}/monitorix/cgi-bin/monitorix.cgi +%attr(777,apache,apache) %{_datadir}/monitorix/imgs +%attr(755,root,root) %{_localstatedir}/lib/monitorix/usage +%config(noreplace) %{_localstatedir}/lib/monitorix/reports/*.html +%{_localstatedir}/lib/monitorix/reports/send_reports +%doc %{_mandir}/man5/monitorix.conf.5.gz +%doc %{_mandir}/man8/monitorix.8.gz +%doc Changes COPYING README README.nginx README.FreeBSD README.OpenBSD README.NetBSD docs/monitorix-alert.sh docs/monitorix-lighttpd.conf + +%changelog +* Thu Sep 01 2005 Jordi Sanfeliu +- Release 0.7.8. +- First public release. +- All changes are described in the Changes file. diff --git a/docs/monitorix.sysconfig b/docs/monitorix.sysconfig new file mode 100644 index 0000000..e5c457e --- /dev/null +++ b/docs/monitorix.sysconfig @@ -0,0 +1,3 @@ +# Here you can specify your Monitorix command line options. +# +#OPTIONS="" diff --git a/logo_bot.png b/logo_bot.png new file mode 100644 index 0000000000000000000000000000000000000000..ec89dd9b84490e3e15b750bce8c88bfc8fde000d GIT binary patch literal 1870 zcmV-U2eJ5xP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01m_e01m_fl`9S#00007bV*G`2iXi9 z5HcbH>{NsR00z!UL_t(|+U=ZMj1)x_hQD1HK^m0XB7-OaMi7@(1EK=P*p`>5i9{ei zVDJ(}ypWjn61LUrh9g#mtOl%HamN&s=H40U;n97U9*rNL4pJc5+q2F;ABUgUxDL#yMV?LZAU37 zaz>k5fj3LES*N79IT`l)ir8sr}sxELBphjr)Vo zVE;Tn& zvH>Flw5^0}BVzVkp7gOV?FCUSa^Lz^7(%;{&2hbZRucYXRiwOAG&+$>h zMZn9ZT}e?Fci*B`whqghEsUxizu(Xp&Hf*J?BDkSWsBUm`Vh*tw@esq3fS>Dh0^DJ z?9cQ9vPJG&7_#j&N#nTQz%pdp9_J)MNwG?2Y&(E<;2YpJCB<8DW?43!2eA5Mk_l7un9pa3DX?3&GSy$0ZJ;06kNKZAfaU^nm)uu4gBq(u8pi}_R~MZ4pAjle^| zRocg+z-C~HlH$usvrC_Qb}9GEN^9hEN+)#-fjfalCB><5VxP_GTQ;4qE2^^&F!$ZI zX4CnLi|W+t2sY8E_eD0Hzq-;jTUN(*Taqx@Qh$ffwHrzd+B|)qr-A9fV4x2$1egIl z3uG(VRMo`U2HXLhr6<}D;5uNv<9g$JVz$@N=RTS&uL4tn{uOj@8DJ85S|*pew&?F! z7NT_mi_3;l$Mx!gGc2>YLo?W>Z07|`4t&YxxZXnG9pJPw126$u+SAqMR(J&RL5 zwJ^AZxY;Ju3(hO2_(agM}iL68biXIwWP$X@+(xJ-GJJ`XPX+y;DCp}MsI zYb?e00{2_&tFr0*zMy1FhalT2nmlI*RJAT-b6jrR}C$%h=bC@Fr_4{JX#-{*RB0u0v2N{Sbh6fH`McY*hOR3j=x z;d2{sqmp8K753v=fp;yFbC_XUkxl1+sS4SY6bAt_1)l^A2$+c;&ytEeIm1$Cvyx)B zaqsQG)(Y2Jn=N~Qwlz^yh{EUfN{Y5B_W3EF(0*d+1gt1^fv{^fTPVFCL~>vYr4uaW zTYcJXvDhXAoaM#%gPuhcKJTekXSKS0OX2*RAC_m+`QO8mEgh0<<{sOz0FE}4Nf-|J zv^x-H-_8h8CljLZ`EU*T{alHAy;iPqHOOXWqAf~_e3@&EFp>-tfBCd)@8PvpwGf5R z?KSB4MLzc7*f;jOO*S)07!xvtnltmS5QEu2#6von5rxmSQ1eoIcaK*>wvi#pHlUki z`_(7IC7}IK49ONNpY=P?>nVLec6KJ0nh=<5j_aLfA&;4nwgLM~R0&JAR!jLbpLUm6 zY^^aQTO55hRqanhVe88%Ul(Od2fXpl5@kCAv@c$>ZL*Y4cU*6xF%g=49>}H`k}Wnq zYgM}xxZENt=DYIwnOtggRAf7-qzIA)6)W2Zmhw7awc~oD^`M`v({9^d*!wXgTikqp z)MEP#*l5^Nz{Axh+pcbe(EpH4Z(MG$)R_W&=eXVhU>|V4rOxL{im&6ww7B@JRqb5h zMx&^M!hb%neW7_lCYKr>glr=N_G4!^$!4DXXr^#lz(ilYKB)ml{+Rvgu9R)^3ok55_4ACB^F$PGppOpLYb9qojD7m?H*0H`DbP)IQ+TqQBn+ z{x<3i2JWerve`muyG2sNgi`d0jPVpsf^N|dp#%6$XJC&3870Ms^b(wmK5JDQLg9N6 zCRS$C`3^Yo&h%&C6HC1ZGr3eh5+q2FAVGoz2@)hokidq20Y_jzH~wAF$^ZZW07*qo IM6N<$f&z1I`2YX_ literal 0 HcmV?d00001 diff --git a/logo_top.png b/logo_top.png new file mode 100644 index 0000000000000000000000000000000000000000..7b055b6e0b126bf0b361123a91767f7a1edfe54e GIT binary patch literal 4021 zcmX9>2{=^k+aHa6n;5%P(k$sCncA3dqwyY_7(`HndnG%sK+4q@bcxy08 zFUB^5CS{+o%+S1i=l%ZIxz0Jy^IZ4&o#$Sj`~Kbcov+x42+9e9Kp+u2+ev{VWSP?+kddGo4qW%BfTt!-< z^1vcryqzPQk0N|bOb6CLba(_T$;QLI;x8g^+z5$@2VIN}35*Z9u9OrJAFgC$=jiO2 zDJl&DL5|v8y5M$eYOO4#Sz%0J(9(EaS^v0lhw&AD7e28 zK4$pQtVs8jmUF)EwB77|kjpI&c`ncD&?y4Tm%f+h-QxbNA``JcI25tbITC#Mb7<&A z9P>|I!o-&zN(y=CV0~|7qfHU7s4gLxYxT-m9Szww)Iw0!Ju?TP?c*}kxH)5;Xv%sj zu0D4~XWKmNOoi7g=kI;|*{6v)b?)N))OM*{2*RC|XroCK%zZt((Dn+q8Y*zD$w|XQ zU83b{i46&Mfw98p@A+~XOiEM(4RUoIS%Ke4=V|9_pJbILH5Z%mRa}0hjHL&Cy_)*c zD}B*ylDRUWJZ&^@#?MwmooLW#xV+uOqX)f3X`D50ersyYe#!KHCt;dT_8Zx&o}Om( zB`Kj4zJ`w^B+#yq67kjM=#+VbpG|HW@xs{KWn0s3I{1f@y$phT79*)Vq${|2DOM{r z$ilwJ%4YLL1-mwavM$F9BPSEyX{IX_1ZQ5&VwRVi3epWM7s4npFg>G>D=)n6l$^R{ zo{-Ws7^AQBm=j%sSpdmT$j{OSilfM?B!?n-o;ox3tvqQBf-31B6@W50-r(LQrC!ULo#+r0H5 zKOlzT{J<0v-ll;q(@ZC;Uf(MU?=G&&H@Q3EOKH4jKZvYs=l0T6KNLVcPAp-*FlHE- z&jxCy54Uzb@9YL=g?+z`7oJZUDIip5Y1;h3Y{Aw#QeXQC_ot!@E&ysjqpOLPi$IU! zFG%A3glKyNJ3^R9ewy&Hg_MyqQ^6h5=YuUsL|ia?Xlkvtv(?)t-E?E(I9K;0)WPm) z8XR$R+dwV0z=&zSfLd|F{fFG!|RU?g4Q>*ST3kZ{zUO{I<8PjRg>%4DShM zQ*;uy-U#Z^9XSC+G>P0eTcjtHu195+wz+d81mQk0NXtf%hqZO=D}CC%G~A}_KWpyl z5+@i>V^Bttc$Wg*jf~CS?@U*93G78=)3b(pJ3wU3`rl&b*juf?higcp|v(Pq*UpAfGu_ zDMkw0cD(X?Wcl0}=Ao3BZ%Y-9*u|<}pFSx5e4MNbhWNC0EyhOwP7perhI87qz6_Hy;91Nt zd48(It4(u%$==Wf>AW{y1;^2Ab$y4>*M^)bHl|5M>p$1^lyf!tT7eNr1fg+OLsoSE zI4Q9nR7Y6-MMFI}5^8fy2iZ5l;MkBqxEubZ-+3)f_LOm_mvhLHO9jGM!@%{Hyqf60 z71tJw&&^E?$f!8mSWx*IUWatm49e))fZHx@nb-wsqnw`6)Py+VXWtQx#*c{lkL1*A zu?sDHn(TB^#CrH?*l{+kD6bAQ2wBqu-ynt64)_E~CwyPhx z&_H!8CyEZNvMfFlsG{ry-r!d+yTfXp`P1q_OKOupTG49{Uz0|403923Q4S-WY?t$~ zw)3lU9#p9e75kYGdXOI3mZLqrcHd7y!$04xwOannD%{5sf)4m`{7|%Mc-#(giuO~Y zFJ|Y+1QaHSG?(CSBgQvv0uFIMCV%auvAT3Nk>GSnan_}x;ZFnJ?)6YNU#aWHimOm? zhGYfgXUa&}^V)%3;idzJex#TlEToMUJtXD-q~DqlA<))g+F*B?H8uQ8>Y%1C8Fl5) z-sS6~7_v;z&JB=55ef(*Mce-RBKj@YiKMEUsM9pembuz`Z+&G?Gou1E9ybZ;_f_>x8W@hWm zJiSjhK3UndB|JYf#mK4gCJ%BhW509B=|5c0Wny*e3j04xjM*3UT_&)&6Rzk=XXEDX z?6&#>#!>*kk9JPS<)$nnng1x--Iz@=5#)U$nqIgk91JNm;zkiG;B|5Rpm$IMn zPRpOqMUg&P_xpbKGbgo`kJ~*kbn(n zk||THQb+#6fLXcn+L+m2Gs7GRv4qe;XybodHqM=#MmDK&{5QRc*0T;4mEMdCYO=cD z)ziDwUFh9uR?V*Xy?aHnH3@)%82!%k&6LkwTgPtFl6fYHtkST&*=gU=77Vnt?ZoW; z82X(mnIUe~eT=~vtF#L^;Y%qaS&6)LKs1C9v@aCRI>KB0gfSz29PaS|_w8|`o0P~) znRflmg4UU6Sa_7iya^my3Kco$x_Xo+!BJ2eIJ6BTqz;L8pGkk%wY$1Y`259GvdILi zR4H$L<66$uoG1J2@tLos#teDbQT#`#jj-tEqz_W9l0JqIHYT{)K{4cXir3d&TSN)> z;CPSYL4aJyo4oal##@lUTeVuTBNv|drs?VrA1@v#1@eDwIAuNZ?t<~xg@3oLx8z%t zW&;m#4c&&BTWA51EI6-*asYg^mgA{E%_=?o@ggHuA0<%!vpGLWEE*T{md-b?yrHd) zx31f$>`Oe*)`p!**vc7jBjSdv{^_lw**MwNERMzD?SHLQH!ECzOZ z;GV?$-sS6^pF_zOV1^L?R!-%q^e0Pc!0w2By!Y&rT-TdFLjJ&6SZwJtjXhyFr0`M%+y?M`shU!ezPc5J|X zVHuYFRr{#sNNp<}hCKFb)AM`OecljWXeTxqja6|NTX;T!{_ZOaM+2Wo$15os4^}~= z{F`Rc*v}kmmpG}Neq@C(FCM0DCjLK}1SQ41!Kyg7YL}yVJoc^}hf5@tm-a5`0P*!p zGifnT;+jd$KP1Zr?tHZ?^L;1LYun9jpO*82$y81sVr3!!V~uDhkFhCs?gB3 zf`XQePd<`(hJeM``3Ea+=b1*0oS#Bd_x=Pv+Wws?;cc}?<_rC{&-g4`arq;=DyT~b zA8PBu8E=km^WdJ$$NiNa(VP2=AFJ{@h6j#zKA1-Sm!s@))d?Aj{o;7_!LTR#)4&f@ zlHL|p8Sn>)wHnxY`M<297bpfvxkPK|O*ag?0+i9!{`3t}z2pSTof`LK?u~a8k)<(|rN=>TmV{0?iZIXk*y-D8+EQBjlq{GmfxngCJdm@!6*iLJgEyPtZl(Jsu*t<{V5M~jyg>h$i1q1Yf7j__lCBBYc%$p1=~{Z^?7HrwDM(i#LG6pz!d` z?PFw3DFYP}qC=+p>N|;b@UGr_%Nh(jWPaC!=#*umL5Hp(H+Nv*;rf+0P@DKH-u4u@-W0dI)&j& zuVX$HQa}8?c(hN6yRyA`fVvL$mu}Xtc|rGdU}RRHsff!g{i()TtL*wio18z{jrrNF z-0Zpy6MN?$ANO4k##;6T3BnhO^1cvhac@n(5D^-vzi?%>Kv~oMs~?$~Pd0~mzw9?O zxUzHRHW!9lbQqzn%~QFDF}Qca=|~mlZ5}uy!MAz;T|2LLcc1r-51dr8x2i<5A>SqZ z$A9NQ$3)%~t(t&Dx6PMyC2mWcr(52xL2{$=abNu8-ZTP?(D(#vLLxxRT`+BQigi(85c9BczxJ*wcc%P@H&o zFMVEU^W}y~7uXD(bdp@Ksj-=Yh@!>;%56RTa@j@z$E2F>s?4CG^H<8tqeaAm=fSiG z%a+OUw@3h^INR4?4Ulw!F=U +.\" +.\" This is the man page for the monitorix.conf configuration file. +.\" +.TH monitorix.conf 5 "Sep 2012" 2.6.0 "Monitorix configuration file" +.SH NAME +monitorix.conf \- Configuration file for Monitorix. +.SH SYNOPSIS +Monitorix is a free, open source, lightweight system monitoring tool designed to monitor as many services and system resources as possible. It has been created to be used on production UNIX/Linux servers, but due to its simplicity and small size may also be used to monitor embedded devices as well. +.P +It consists mainly of two programs: a collector, called \fBmonitorix\fP, which is a Perl daemon that is started automatically like any other system service, and a CGI script called \fBmonitorix.cgi\fP. +.P +Every time \fBmonitorix\fP is started it reads the configuration file from the path specified in the command line (using the \fB-c\fP option), and once checked, it creates the \fIindex.html\fP file that will act as the Monitorix main page. +.P +It also creates a file called \fI$BASE_DIR/cgi-bin/monitorix.conf.path\fP that includes the absolute path of the configuration file. This file will be read by \fBmonitorix.cgi\fP to determine the exact location of the configuration file. If for any reason it is unable to locate this file, Monitorix will try two alternate locations: \fI/etc/monitorix.conf\fP and \fI/usr/local/etc/monitorix.conf\fP. +.SH DESCRIPTION +The configuration file is a Perl file where values are directly assigned to variables that Monitorix uses during normal operation; you should take care to conform to basic Perl syntax. +.SH CONFIGURATION OPTIONS +Because this file follows the Perl syntax, you will find different type of options (scalar or normal variables, arrays and associative arrays), each one prefixed with $, @ and % respectively. This is important to keep in mind as the prefix symbols indicate what type of values each option accepts. +.P +Remember to enclose all values with double quotes. +.P +.BI TITLE +.RS +A description of the server, where it is located, the Company name, etc. +.P +Default value: \fIPlace a Title Here\fP +.RE +.P +.BI HOSTNAME +.RS +The name of the host. +.P +Default value: none +.RE +.P +.BI THEME_COLOR +.RS +RRDtool comes with a default white theme, and since Monitorix introduces its own black theme, you have two predefined themes to choose from. +.P +Default value: \fIblack\fP +.RE +.P +.BI REFRESH_RATE +.RS +The refresh rate (in seconds) of the statistics web page displayed in your browser. If set to 0, page refreshing is disabled. +.P +Default value: \fI150\fP +.RE +.P +.BI IFACE_MODE +.RS +The interface mode defines the manner in which data is shown in the browser. Since version 1.4.0 it has been possible to display the graphic data using plain text tables. This allows Monitorix to be used by those running screen reader software, and also simplifies automatic data processing through scripts. +.P +The possible values are: +.RS +\fIgraph\fP for rendered graphs +.br +\fItext\fP for plain text representation +.RE +.P +Default value: \fIgraph\fP +.RE +.P +.BI ENABLE_ZOOM +.RS +Zoom allows double clicking any graph in order to see a larger version (zoomed in). This is especially useful for seeing additional detail. +.P +Default value: \fIY\fP +.RE +.P +.BI NETSTATS_IN_BPS +.RS +This option toggles network values between bits and bytes per second. +.P +Default value: \fIN\fP +.RE +.P +.BI DISABLE_JAVASCRIPT_VOID +.RS +This option enables or disables the use of use javascript:void-URLs when opening windows with zoomed graphs. Some people likes to open links in the background by pressing the middle mouse button in Firefox, and with the default javascript:void-URLs the only they get is an empty window with nothing in it. +.P +Default value: \fIN\fP +.RE +.P +.BI BASE_DIR +.RS +This is the absolute path to the directory where all the web elements are located: +.P +.RS +\fIcgi-bin/\fP \fBmonitorix.cgi\fP script directory +.br +\fIimgs/\fP .png graph images directory +.br +\fIindex.html\fP Monitorix main page +.br +\fIlogo_bot.png\fP Monitorix bottom logo +.br +\fIlogo_top.png\fP Monitorix top logo +.br +\fImonitorixico.png\fP Monitorix favicon logo +.RE +.P +Default value: \fI/usr/share/monitorix/\fP +.br +(depends on the operating system) +.RE +.P +.BI BASE_LIB +.RS +This is the absolute path to the directory where all of the monthly reports, daily traffic usage, and RRD files are located: +.P +.RS +\fIreports/\fP monthly reports localization directory +.br +\fIusage/\fP daily traffic usage data directory +.br +\fI*.rrd\fP RRD files +.RE +.P +Default value: \fI/var/lib/monitorix/\fP +.br +(depends on the operating system) +.RE +.P +.BI BASE_URL +.RS +This is the URL prefix that Monitorix utilizes when refering to its own pages and files. +.P +Default value: \fI/monitorix\fP +.RE +.P +.BI BASE_CGI +.RS +This is the URL prefix that Monitorix utilizes when refering to \fBmonitorix.cgi\fP. +.P +Default value: \fI/monitorix-cgi\fP +.RE +.P +.BI LOG_FILE +.RS +This is the path to the Monitorix log file. Please check this file periodically and especially after every update to confirm proper operation. +.P +Default value: \fI/var/log/monitorix\fP +.RE +.P +.BI SECURE_LOG +.RS +This is the path to the system log (also known as \fIsecure\fP, \fIauth.log\fP, etc.) Monitorix uses this file to report SSH, POP3, FTP and Telnet successful logins. +.P +Default value: \fI/var/log/secure\fP +.RE +.P +.BI MAIL_LOG +.RS +This is the path to the mail log file. Monitorix uses this file to report messages sent (supporting Sendmail and Postfix formats), and the MailScanner log format for spam-mail and virus-mail alerts. +.P +Default value: \fI/var/log/maillog\fP +.RE +.P +.BI MILTER_GL +.RS +This is the path to the dump file of \fImilter-greylist\fP. +.P +Default value: \fI/var/lib/milter-greylist/db/greylist.db\fP +.RE +.P +.BI IMAP_LOG +.RS +This is the path to the IMAP (Dovecot or UW-IMAP) log file. Monitorix uses this file to report IMAP and POP3 successful logins. +.P +Default value: \fI/var/log/imap\fP +.RE +.P +.BI HYLAFAX_LOG +.RS +This is the path to the Hylafax log file. Monitorix uses this file to report successful FAX dispatches. +.P +Default value: \fI/var/spool/hylafax/etc/xferfaxlog\fP +.RE +.P +.BI CUPS_LOG +.RS +This is the path to the CUPS page log file. Monitorix uses this file to report on print jobs. +.P +Default value: \fI/var/log/cups/page_log\fP +.RE +.P +.BI FAIL2BAN_LOG +.RS +This is the path to the Fail2ban log file. Monitorix uses this file to report IP addresses banned. +.P +Default value: \fI/var/log/fail2ban.log\fP +.RE +.P +.BI SPAMASSASSIN_LOG +.RS +This is the path to the Spamassassin log file. Monitorix uses this file to report spam-mail alerts. +.P +Default value: \fI/var/log/maillog\fP +.RE +.P +.BI CLAMAV_LOG +.RS +This is the path to the Clamav log file. Monitorix uses this file to report virus-mail alerts. +.P +Default value: \fI/var/log/clamav/clamav.log\fP +.RE +.P +.BI CG_LOGDIR +.RS +This is the path to the CommuniGate logs directory. Monitorix uses these files to report the number of mail messages successfully received and sent, and to report IMAP and POP3 successful logins. +.P +Default value: \fI/var/CommuniGate/SystemLogs/\fP +.RE +.P +.BI SQUID_LOG +.RS +This is the path to the Squid log file. Monitorix uses this file to report on Squid Proxy requests. +.P +Default value: \fI/var/log/squid/access.log\fP +.RE +.P +.BI IMAP_DATE_LOG_FORMAT +.RS +This is the Dovecot date format as it appears in the \fBIMAP_LOG\fP file. +.P +Default value: \fI%b %d\fP +.RE +.P +.BI ENABLE_ALERTS +.RS +This enables or disables the alert capabilities that were introduced in Monitorix version 1.4.0. Only two alerts are currently implemented; one for the average CPU load and one for the root filesystem disk use. They work as follows: +.P +The CPU load average uses the third value (the one that represents the last 15 minutes of load average), and if it reaches the \fBALERT_LOADAVG_THRESHOLD\fP value for the interval of time defined in \fBALERT_LOADAVG_TIMEINTVL\fP, Monitorix will execute the external alert script defined in \fBALERT_LOADAVG_SCRIPT\fP. +.P +For the root filesystem disk use, if the percentage of disk space used reaches the \fBALERT_ROOTFS_THRESHOLD\fP value for the interval of time defined in \fBALERT_ROOTFS_TIMEINTVL\fP, Monitorix will execute the external alert script defined in \fBALERT_ROOTFS_SCRIPT\fP. +.P +The default Monitorix installation includes an example alert shell-script called \fBmonitorix-alert.sh\fP which you can use as a base for your own script. +.P +Default value: \fIN\fP +.RE +.P +.BI ALERT_LOADAVG_TIMEINTVL +.RS +This is the period of time (in seconds) that the threshold needs to be exceeded before the external alert script is executed. +.P +Default value: \fI3600\fP +.RE +.P +.BI ALERT_LOADAVG_THRESHOLD +.RS +This is the value that needs to be reached or exceeded within the specified time period in \fBALERT_LOADAVG_TIMEINTVL\fP to trigger the mechanism for a particular action, which in this case is the execution of an external alert script. +.P +The value of this option is compared against the last 15 minutes of CPU load average. +.P +Default value: \fI5.0\fP +.RE +.P +.BI ALERT_LOADAVG_SCRIPT +.RS +This is the full path name of the script that will be executed by this alert. +.P +It will receive the following three parameters: +.P +1st - the value currently defined in \fBALERT_LOADAVG_TIMEINTVL\fP +.br +2nd - the value currently defined in \fBALERT_LOADAVG_THRESHOLD\fP +.br +3rd - the current 15min CPU load average +.P +Default value: \fI/path/to/script.sh\fP +.RE +.P +.BI ALERT_ROOTFS_TIMEINTVL +.RS +This is the period of time (in seconds) that the threshold needs to be exceeded before the external alert script is executed. +.P +Default value: \fI3600\fP +.RE +.P +.BI ALERT_ROOTFS_THRESHOLD +.RS +This is the value that needs to be reached or exceeded within the specified time period in \fBALERT_ROOTFS_TIMEINTVL\fP to trigger the mechanism for a particular action, which in this case is the execution of an external alert script. +.P +The value of this option is compared to the current root filesystem disk usage. +.P +Default value: \fI100\fP +.RE +.P +.BI ALERT_ROOTFS_SCRIPT +.RS +This is the full path name of the script that will be executed by this alert. +.P +It will receive the following three parameters: +.P +1st - the value currently defined in \fBALERT_ROOTFS_TIMEINTVL\fP +.br +2nd - the value currently defined in \fBALERT_ROOTFS_THRESHOLD\fP +.br +3rd - the current root filesystem disk usage +.P +Default value: \fI/path/to/script.sh\fP +.RE +.P +.BI GRAPH_ENABLE +.RS +This enables or disables the monitoring of each graph. Placing a \fIY\fP on a desired graph and restarting Monitorix will automatically create the RRD file for that graph and start gathering information according to its settings. +.RE +.SS System load average and usage (system.rrd) +Only the limit and rigid values may be set here. +.SS Global kernel usage (kern.rrd) +.BI KERN_GRAPH_MODE +.RS +This changes the layout of the kernel usage graph, the possible values are \fIR\fP for a real graph, or \fIS\fP for a stacked graph (every line or area is stacked on top of the previous element). +.P +Default value: \fIR\fP +.RE +.P +.BI KERN_DATA +.RS +This is the list of values offered in modern Linux kernels. Older Linux kernels or other Operating Systems may not have all of them. Placing a \fIY\fP or an \fIN\fP will enable or disable the value in the graph. +.RE +.SS Kernel usage per processor (proc.rrd) +.BI PROC_MAX +.RS +This is the number of processors or cores that your system has. There is no limit, however keep in mind that every time this number is changed Monitorix will resize the \fIproc.rrd\fP file accordingly, removing all historical data. +.P +Default value: \fI4\fP +.RE +.P +.BI PROC_PER_ROW +.RS +This is the number of processor graphs that will be put in a row. Consider the interaction of this parameter with the \fBPROC_SIZE\fP and \fBPROC_DATA\fP options (below) in order to adjust the size and number of graphs in relation to your horizontal screen size. +.P +Default value: \fI2\fP +.RE +.P +.BI PROC_SIZE +.RS +This option sets the size of all processors graphs. +.P +The possible values are: +.RS +\fImain\fP for 450x150 graphs +.br +\fImedium\fP for 325x150 graphs +.br +\fImedium2\fP for 325x70 graphs +.br +\fIsmall\fP for 200x66 graphs +.br +\fImini\fP for 183x66 graphs +.br +\fItiny\fP for 110x40 graphs +.RE +.P +Default value: \fImedium\fP +.RE +.P +.BI PROC_DATA +.RS +This option will completely enable or disable the legend in the processor graphs. +.P +Default value: \fIY\fP +.RE +.SS HP ProLiant System Health (hptemp.rrd) +.BI HPTEMP_1 +.br +.BI HPTEMP_2 +.br +.BI HPTEMP_3 +.RS +These arrays will hold the defined temperature sensors for each graph. You must have installed the latest version of \fIhplog\fP that comes with HP ProLiant System Health Application and Command Line Utilities. +.P +Each graph has a limited number of IDs: +.P +\fBHPTEMP_1\fP up to 8 IDs +.br +\fBHPTEMP_2\fP up to 6 IDs +.br +\fBHPTEMP_3\fP up to 6 IDs +.P +The following is a configuration example of selected IDs: +.P +# hplog -t +.br +ID TYPE LOCATION STATUS CURRENT THRESHOLD +.br + 1 Basic Sensor Ambient Normal 75F/ 24C 107F/ 42C +.br + 2 Basic Sensor CPU (1) Normal 104F/ 40C 179F/ 82C +.br + 3 Basic Sensor CPU (2) Normal ---F/---C 179F/ 82C +.br + 4 Basic Sensor Memory Board Normal ---F/---C 188F/ 87C +.br + 5 Basic Sensor Memory Board Normal 82F/ 28C 188F/ 87C +.br + 6 Basic Sensor Memory Board Normal ---F/---C 188F/ 87C +.br + 7 Basic Sensor System Board Normal 89F/ 32C 192F/ 89C +.br + 8 Basic Sensor System Board Normal ---F/---C 192F/ 89C +.br + 9 Basic Sensor System Board Normal 84F/ 29C 192F/ 89C +.br +10 Basic Sensor System Board Normal 118F/ 48C 230F/110C +.br +11 Basic Sensor System Board Normal 96F/ 36C 192F/ 89C +.br +12 Basic Sensor System Board Normal 84F/ 29C 154F/ 68C +.br +13 Basic Sensor System Board Normal 87F/ 31C 154F/ 68C +.br +14 Basic Sensor System Board Normal 89F/ 32C 156F/ 69C +.br +15 Basic Sensor System Board Normal 93F/ 34C 161F/ 72C +.br +16 Basic Sensor Ambient Normal ---F/---C 192F/ 89C +.br +17 Basic Sensor System Board Normal ---F/---C 192F/ 89C +.br +18 Basic Sensor SCSI Backplane Normal 32F/ 0C 140F/ 60C +.P +.RS +our @HPTEMP_1 = ( +.br + "2", +.br + "3", +.br +); +.br +our @HPTEMP_2 = ( +.br + "1", +.br + "5", +.br + "18", +.br +); +.br +our @HPTEMP_3 = ( +.br + "7", +.br + "9", +.br + "10", +.br + "11", +.br + "12", +.br + "13", +.br +); +.RE +.RE +.SS LM-Sensors and GPU temperatures (lmsens.rrd) +.BI SENSORS_LIST +.RS +You may specify in this associative array the sensors you want to monitor with the same names as they appear in your \fIsensors\fP command. +.P +For example, imagine a \fIsensors\fP output like this: +.P +# sensors +.br +coretemp-isa-0000 +.br +Adapter: ISA adapter +.br +Core 0: +51.0°C (high = +78.0°C, crit = +100.0°C) +.br +.P +coretemp-isa-0001 +.br +Adapter: ISA adapter +.br +Core 1: +49.0°C (high = +78.0°C, crit = +100.0°C) +.br +.P +f71882fg-isa-0a00 +.br +Adapter: ISA adapter +.br +3.3V: +3.30 V +.br +Vcore: +1.21 V (max = +2.04 V) +.br +Vdimm: +1.82 V +.br +Vchip: +1.38 V +.br ++5V: +5.00 V +.br +12V: +14.37 V +.br +5VSB: +4.33 V +.br +3VSB: +3.30 V +.br +Battery: +3.22 V +.br +CPU: 2035 RPM +.br +System: 1765 RPM ALARM +.br +Power: 2110 RPM ALARM +.br +Aux: 2080 RPM ALARM +.br +M/B Temp: +36.00 C +.br +CPU Temp: +29.00 C +.P +Then you may want to configure the \fBSENSORS_LIST\fP associative array as: +.P +.RS +our %SENSORS_LIST = ( +.br + "CORE0" => "Core 0", +.br + "CORE1" => "Core 1", +.br + "MB0" => "M/B Temp", +.br + "CPU0" => "CPU Temp", +.br + "FAN0" => "CPU", +.br + "FAN1" => "System", +.br + "FAN2" => "Power", +.br + "FAN3" => "Aux", +.br + "VOLT0" => "3.3V", +.br + "VOLT1" => "VCore", +.br + "VOLT2" => "Vdimm", +.br + "VOLT3" => "Vchip", +.br + "VOLT4" => "\\\\+5V", +.br + "VOLT5" => "12V", +.br + "VOLT6" => "5VSB", +.br + "VOLT7" => "3VSB", +.br + "VOLT8" => "Battery", +.br + "GPU0" => "nvidia", +.br +); +.RE +.P +Note that you need to precede the plus and minus signs in the voltage labels with double forward slashes. +.P +The last one, \fIGPU0\fP, is set here just in case you have an NVIDIA card and want to monitor its temperature. Currently only NVIDIA cards are supported so the value \fInvidia\fP is mandatory. +.P +This array has the following maximums allowed: +.P +.RS +Up to 16 \fICORE\fP keys +.br +Up to 2 \fIMB\fP keys +.br +Up to 4 \fICPU\fP keys +.br +Up to 9 \fIFAN\fP keys +.br +Up to 12 \fIVOLT\fP keys +.br +Up to 9 \fIGPU\fP keys +.RE +.RE +.SS NVIDIA temperatures and usage (nvidia.rrd) +.BI NVIDIA_MAX +.RS +This is the number of NVIDIA cards currently plugged in your system. +.P +The maximum allowed is 9. +.P +Default value: \fI1\fP +.RE +.SS Disk drive temperatures and health (disk.rrd) +This graph is able to monitor an unlimited number of disk drives. +.P +.BI DISK_LIST +.RS +This is a two-dimensional array of groups of disk device names that you want to monitor. Each group will become a graph and there may be an unlimited number of groups. +.P +WARNING: Every time the number of groups in this list changes, Monitorix will resize the \fIdisk.rrd\fP file accordingly, removing all historical data. +.P +To collect the disk drive temperatures and health the commands \fIsmartmontools\fP or \fIhddtemp\fP are required. +.P +It is recommended that you first check if either \fIsmartctl\fP or \fIhddtemp\fP are able to collect data from the disk drive(s) that you plan to monitor. You may test this with the following command: +.P +.RS +# hddtemp /dev/sda +.br +/dev/sda: WDC WD1600AABS-00M1A0: 48°C +.P +.RE +If you see good results as above, you can add it in the list like this: +.P +.RS +our @DISK_LIST = ( +.br + [ +.br + "/dev/sda", +.br + "/dev/sdb", +.br + ], +.br +); +.RE +.P +The maximum number of disk device names allowed per group is 8. +.RE +.SS Filesystem usage and I/O activity (fs.rrd) +This graph is able to monitor an unlimited number of filesystems. +.P +.BI FS_LIST +.RS +This is a two-dimensional array of groups of mounted filesystems that you want to monitor. Each group will become a graph and there may be an unlimited number of groups. +.P +WARNING: Every time the number of groups in this list changes, Monitorix will resize the \fIfs.rrd\fP file accordingly, removing all historical data. +.P +Take special care to use the same name as appears in the output of the \fIdf\fP command (the \fIswap\fP device is a special case). An example would be: +.P +.RS +our @FS_LIST = ( +.br + [ +.br + "/", +.br + "swap", +.br + "/boot", +.br + "/home", +.br + "/mnt/backup", +.br + ], +.br +); +.RE +.P +The maximum number of filesystems allowed per group is 8. +.RE +.P +.BI FS_DESC +.RS +This associative array complements the \fBFS_LIST\fP array. It basically allows you to change the name that will appear in the graph, hiding the real name of the mount point. If no association is defined, then Monitorix will display the name specified in the \fBFS_LIST\fP array. +.P +.RS +our %FS_DESC = ( +.br + "/" => "Root FS", +.br + "/home" => "My Home", +.br + "/mnt/backup" => "Backups", +.br +); +.RE +.P +You can define as much entries as you want. +.RE +.P +.BI FS_DEV +.RS +This associative array complements the \fBFS_LIST\fP array. Monitorix tries itself to detect automatically the device name associated to each filesystem defined in the \fBFS_LIST\fP array to show its I/O activity. If you feel Monitorix failed to detect it then you can help it using this associative array. +.P +.RS +our %FS_DEV = ( +.br + "/" => "/dev/sda1", +.br + "/home" => "/dev/mapper/dm-0", +.br + "/mnt/backup" => "/dev/mapper/dm-1", +.br +); +.RE +.P +You can define as much entries as you want. +.RE +.SS Network traffic and usage (net.rrd) +.BI NET_LIST +.RS +This is the list of network interfaces that you may want to monitor. An example would be: +.P +.RS +our @NET_LIST = ( +.br + "eth0", +.br + "eth1", +.br +); +.RE +.P +The maximum number of entries allowed is 10. +.RE +.P +.BI NET_DESC +.RS +This is the array where each network interface listed in \fBNET_LIST\fP is described. Put one description for each interface listed. An example would be: +.P +.RS +our @NET_DESC = ( +.br + "FastEthernet LAN", +.br + "ADSL 10Mbs Internet", +.br +); +.RE +.P +The maximum number of entries allowed is 10. +.RE +.P +.BI NET_RIGID +.RS +This is the location where the scaling of the network graph can be specified. +.P +The possible values are: +.P +\fI0\fP No rigid actually, no lower-limit and no upper-limit. +.br +\fI1\fP No rigid actually, but with lower-limit and upper-limit. +.br +\fI2\fP Rigid with lower-limit and upper-limit. +.P +There must be an entry here for each network interface listed in \fBNET_LIST\fP. An example would be: +.P +.RS +our @NET_RIGID = ( +.br + "0", +.br + "2", +.br +); +.RE +.P +The maximum number of entries allowed is 10. +.RE +.P +.BI NET_LIMIT +.RS +This is where you can enter the upper value limit for the graph. Since Monitorix uses bytes/s instead of bits/s, the value entered here must be in bytes. +.P +Remember to put an entry here for each network interface listed in \fBNET_LIST\fP. Following the description of the above example, it would be: +.P +.RS +our @NET_LIMIT = ( +.br + "10000000", +.br + "1000000", +.br +); +.RE +.P +That is: +.P +"Fast Ethernet LAN" means 100Mb/s, which means ~10MB/s which means 10000000 bytes. +.P +and +.P +"ADSL 10Mb Internet" means 10Mb/s, which means ~1MB/s which means 1000000 bytes. +.P +The maximum number of entries allowed is 10. +.RE +.P +.BI NET_GATEWAY +.RS +This is where the network interface that acts as the gateway for this server is defined. This is mainly used if you plan to monitor the network traffic usage of the PCs on your LAN using the \fBPC_LIST\fP option below. +.RE +.SS System services demand (serv.rrd) +.BI SERV_MODE +.RS +This option toggles the way the System Services Demand data is represented in the graph. There are two possible values: +.P +.RS +\fII\fP for incremental style +.br +\fIL\fP for load (spikes) style +.RE +.P +Default value: \fII\fP +.RE +.SS Mail statistics (mail.rrd) +.BI MAIL_MTA +.RS +This option specifies the MTA that Monitorix will use to collect mail statistics. The currently supported MTAs are: +.RS +\fISendmail\fP +.br +\fIPostfix\fP +.RE +.P +NOTE: the \fIpflogsumm\fP utility is required when using \fBPostfix\fP MTA. +.P +Default value: \fIsendmail\fP +.RE +.P +.BI MAIL_GREYLIST +.RS +This option specifies the Greylisting implementation that Monitorix will use to collect statistical information. In the future more Greylisting software will be supported. +.P +The currently supported Greylist software is: +.RS +\fImilter-greylist\fP +.RE +.P +Default value: \fImilter-greylist\fP +.RE +.SS Network port traffic (port.rrd) +This graph requires the \fIiptables\fP command on Linux systems, and the \fIipfw\fP command on FreeBSD and OpenBSD systems. +.P +.BI PORT_MAX +.RS +This is the number of network ports that you want to monitor. There is no limit to the number of ports monitored, but keep in mind that every time this number changes, Monitorix will resize the \fIport.rrd\fP file accordingly, removing all historical data. +.P +Default value: \fI9\fP +.RE +.P +.BI PORT_RULE +.RS +This is the rule number that Monitorix will use when using the \fIipfw\fP command to manage network port activity on FreeBSD and OpenBSD systems. Change it if you think it might conflict with any other rule number. +.P +Default value: \fI24000\fP +.RE +.P +.BI PORT_LIST +.RS +You may define here up to \fBPORT_MAX\fP network port numbers. If you see a red color in the background of a network port graph, it means that there is not a daemon listening on that port. This can be useful to know if some service gone down unexpectedly. +.RE +.P +.BI PORT_NAME +.RS +This array complements the \fBPORT_LIST\fP array. Each option pairs with the one in the same position of the array. It basically permits naming network ports. +.RE +.P +.BI PORT_PROT +.RS +This array complements the \fBPORT_LIST\fP array. Each option pairs with the one in the same position of the array. It permits defining the protocol type to be used in the traffic reporting. The protocol type must be valid and supported by your system. +.RE +.SS Users using the system (user.rrd) +Only the limit and rigid values may be set here. +.SS Apache statistics (apache.rrd) +This graph requires that \fImod_status\fP be loaded and \fIExtendedStatus\fP option set to \fIOn\fP in order to collect full status information of the Apache web server. +.P +This graph is able to monitor an unlimited number of local and remote Apache web servers. +.P +.BI APACHE_LIST +.RS +This is a list of URLs of the monitored Apache web servers. +.P +WARNING: Every time the number of entries in this list changes, Monitorix will resize the \fIapache.rrd\fP file accordingly, removing all historical data. +.P +Default value: \fIhttp://localhost:80/\fP +.RE +.SS Nginx statistics (nginx.rrd) +This graph may require adding some lines in the configuration file \fInginx.conf\fP. Please see the \fIREADME.nginx\fP file to determine the exact steps needed to configure Nginx to get status information. +.P +This graph requires the \fIiptables\fP command on Linux systems, and the \fIipfw\fP command on FreeBSD and OpenBSD systems. +.P +.BI NGINX_PORT +.RS +This is the network port the Nginx web server is listening on. +.P +Default value: \fI80\fP +.RE +.P +.BI NGINX_RULE +.RS +This is the rule number that Monitorix will use when using the \fIipfw\fP command to manage Nginx network activity on FreeBSD and OpenBSD systems. Change it if you think it might conflict with any other rule number. +.P +Default value: \fI24100\fP +.RE +.SS Lighttpd statistics (lighttpd.rrd) +This graph requires that \fImod_status\fP is loaded in order to collect status information from the Lighttpd web server. +.P +This graph is able to monitor an unlimited number of local and remote Lighttpd web servers. +.P +.BI LIGHTTPD_LIST +.RS +This is a list of URLs of the monitored Lighttpd web servers. +.P +WARNING: Every time the number of entries of this list changes, Monitorix will resize the \fIlighttpd.rrd\fP file accordingly, removing all historical data. +.P +Default value: \fIhttp://localhost:80/\fP +.RE +.SS MySQL statistics (mysql.rrd) +This graph requires that you create a password protected MySQL user that is NOT granted privileges on any DB. +.P +Example: +.P +mysql> CREATE USER 'user'@'localhost' IDENTIFIED BY 'password'; +.br +mysql> FLUSH PRIVILEGES; +.br +.P +where \fIuser\fP is the new user name and \fIpassword\fP is the password that will be used for that user. +.P +This graph is able to monitor an unlimited number of local and remote MySQL web servers. +.P +NOTE: It is strongly recommended that you restart the MySQL service in order to avoid high spikes that could prevent correct display of the first plotted data. +.P +.BI MYSQL_CONN_TYPE +.RS +This option toggles the way how Monitorix establishes the connection with the MySQL server. There are two possible values: +.P +.RS +\fIHost\fP using the network (hostname and IP address) +.br +\fISocket\fP using a socket file +.RE +.P +Default value: \fIHost\fP +.RE +.P +.BI MYSQL_HOST_LIST +.RS +This is the list of hostnames of MySQL servers. +.P +WARNING: Every time the number of entries of this list change Monitorix will resize the \fImysql.rrd\fP file accordingly, removing all historical data. +.P +Default value: \fIlocalhost\fP +.RE +.P +.BI MYSQL_PORT_LIST +.RS +This is the TCP port number to use for the connection of each hostname listed in the \fBMYSQL_HOST_LIST\fP. +.P +Default value: \fI3306\fP +.RE +.P +.BI MYSQL_USER_LIST +.RS +This is the user name used to connect to each hostname listed in the \fBMYSQL_HOST_LIST\fP. See the example above. +.P +Default value: \fInone\fP +.RE +.P +.BI MYSQL_PASS_LIST +.RS +This is the password used to connect to each hostname listed in the \fBMYSQL_HOST_LIST\fP. See the example above. +.P +Default value: \fInone\fP +.RE +.P +.BI MYSQL_SOCK_LIST +.RS +This is the list of socket files of MySQL servers. +.P +WARNING: Every time the number of entries of this list change Monitorix will resize the \fImysql.rrd\fP file accordingly, removing all historical data. +.P +Default value: \fI/var/lib/mysql/mysql.sock\fP +.RE +.P +Some of the values shown in the graphs are the result of a calculation of two values from either \fISHOW [GLOBAL] STATUS\fP or \fISHOW VARIABLES\fP. The following is an explanation of them: +.P +\fBThread Cache Hit Rate\fP +.br +\fB(1 - (Threads_created / Connections)) * 100\fP +.br +When an application connects to a MySQL database, the database has to create a thread to manage the connection and the queries that will be sent in that connection. The database instructs the kernel to create a new thread, and the kernel allocates resources and creates the thread, then returns it to the MySQL service. When the connection is terminated by the application, MySQL tells the kernel to destroy the thread and free the resources. This create/destroy mechanism causes considerable overhead if the MySQL server has many new connections per second. +.br +If MySQL doesn't destroy the thread when the connection is terminated, but reuses it and assigns it to the next connection then this will decrease the kernel overhead. This is why a high \fBThread Cache Hit Rate\fP improves MySQL performance and decreases the system's CPU usage. +.br +Setting the parameter \fIthread_cache_size\fP in the \fImy.cnf\fP file accordingly will help to correctly balance between having a great thread cache and keeping MySQL memory consumption reasonable. +.br +Higher is better. +.P +\fBQuery Cache Hit Rate\fP +.br +\fBQcache_hits / Qcache_inserts\fP +.br +Higher should be considered better. This value should grow proportionally with the number of executed queries, if the query cache is performing well. Please also have a look at the \fBQuery cache usage\fP percentage to know if your query_cache configuration is appropriate. +.P +\fBQuery Cache Usage\fP +.br +\fB(1 - (Qcache_free_memory / query_cache_size)) * 100\fP +.br +This value should be reasonably far from 100%, otherwise consider incrementing the \fIquery_cache_size\fP parameter in \fImy.cnf\fP. +.P +\fBConnections Usage\fP +.br +\fB(Max_used_connections / max_connections) * 100\fP +.br +This value should be reasonably far from 100%, otherwise consider incrementing the \fImax_connections\fP parameter in \fImy.cnf\fP. +.P +\fBKey Buffer Usage\fP +.br +\fB(Key_blocks_used / (Key_blocks_used + Key_blocks_unused)) * 100\fP +.br +This value should be reasonably far from 100%, otherwise consider incrementing the \fIkey_buffer_size\fP parameter in \fImy.cnf\fP. +.P +\fBInnoDB Buffer Pool Usage\fP +.br +\fB(1 - (Innodb_buffer_pool_pages_free / Innodb_buffer_pool_pages_total)) * 100\fP +.br +This value should be reasonably far from 100%, otherwise consider incrementing the \fIinnodb_buffer_pool_size\fP parameter in \fImy.cnf\fP. +.SS Squid Proxy Web Cache (squid.rrd) +.P +.BI SQUID_CMD +.RS +This command displays statistics about the Squid HTTP proxy process and is the main command used to collect all data. +.P +Default value: \fIsquidclient -h 127.0.0.1\fP +.P +.RE +.BI SQUID_GRAPH_1 +.br +.BI SQUID_GRAPH_2 +.RS +These arrays hold the selected Squid result or status codes to be shown in each graph. Feel free to mix result status and code status in any of the two arrays. +.P +For more information about the list of all the result and status codes, please refer to http://wiki.squid-cache.org/SquidFaq/SquidLogs. +.P +Each graph has a limit number of 9 entries. +.RE +.SS NFS server statistics (nfss.rrd) +.P +.BI NFSS_VERSION +.RS +This option specifies which NFS server version is running in the system in order to correctly gather the correct values. +.P +The possible values are: +.RS +\fI2\fP for NFS version 2 +.br +\fI3\fP for NFS version 3 +.br +\fI4\fP for NFS version 4 +.RE +.P +Default value: \fI3\fP +.P +.RE +.BI NFSS_GRAPH_1 +.br +.BI NFSS_GRAPH_2 +.br +.BI NFSS_GRAPH_3 +.RS +These arrays hold the defined NFS server activity statistics to be shown in each graph. Put every statistic name exactly as they appear in the output of the \fInfsstat\fP command. +.P +Each graph has a limit number of 10 entries. +.RE +.SS NFS client statistics (nfsc.rrd) +.P +.BI NFSC_VERSION +.RS +This option specifies which NFS server version is running in the system in order to correctly gather the correct values. +.P +The possible values are: +.RS +\fI2\fP for NFS version 2 +.br +\fI3\fP for NFS version 3 +.br +\fI4\fP for NFS version 4 +.RE +.P +Default value: \fI3\fP +.P +.RE +.BI NFSC_GRAPH_1 +.br +.BI NFSC_GRAPH_2 +.br +.BI NFSC_GRAPH_3 +.br +.BI NFSC_GRAPH_4 +.br +.BI NFSC_GRAPH_5 +.RS +These arrays hold the defined NFS client activity statistics to be shown in each graph. Put every statistic name exactly as they appear in the output of the \fInfsstat\fP command. +.P +Each graph has the following limit number of entries: +.P +\fBNFSC_GRAPH_1\fP up to 10 entries +.br +\fBNFSC_GRAPH_2\fP up to 10 entries +.br +\fBNFSC_GRAPH_3\fP up to 4 entries +.br +\fBNFSC_GRAPH_4\fP up to 4 entries +.br +\fBNFSC_GRAPH_5\fP up to 4 entries +.RE +.SS BIND statistics (bind.rrd) +This graph requires a BIND server with version 9.5 or higher, and in order to see all statistics provided by BIND you must configure the \fIstatistics-channels\fP like this: +.P +statistics-channels { +.br + inet 127.0.0.1 port 8053; +.br +}; +.P +This graph is able to monitor an unlimited number of BIND servers. +.P +.BI BIND_URL_LIST +.RS +This is a list of URLs of BIND servers status pages. +.P +WARNING: Every time the number of entries in this list changes, Monitorix will resize the \fIbind.rrd\fP file accordingly, removing all historical data. +.P +Default value: \fIhttp://localhost:8053/\fP +.RE +.P +.BI BIND_IN_QUERIES_LIST +.RS +This is a two-dimensional array of RR (Resource Records) types for each BIND server. The RR types defined here will appear in the Incoming Queries graph which shows the number of incoming queries for each RR type. +.P +For a complete list of RR types check the BIND 9 Administrator Reference Manual at . +.P +our @BIND_IN_QUERIES_LIST = ( +.br + [ +.br + "A", +.br + "AAAA", +.br + "ANY", +.br + "DS", +.br + "MX", +.br + "NS", +.br + "PTR", +.br + "SOA", +.br + "SRV", +.br + "TXT", +.br + "NAPTR", +.br + "A6", +.br + "CNAME", +.br + "SPF", +.br + "KEY", +.br + "DNSKEY", +.br + "HINFO", +.br + "WKS", +.br + "PX", +.br + "NSAP", +.br + ], +.br +); +.P +The maximum number of RR types allowed for this graph is 20. +.RE +.P +.BI BIND_OUT_QUERIES_LIST +.RS +This is a two-dimensional array of RR (Resource Records) types for each BIND server. The RR types defined here will appear in the Outgoing Queries graph (_default view) which shows the number of outgoing queries sent by the DNS server resolver for each RR type. +.P +our @BIND_OUT_QUERIES_LIST = ( +.br + [ +.br + "A", +.br + "AAAA", +.br + "ANY", +.br + "DS", +.br + "MX", +.br + "NS", +.br + "PTR", +.br + "SOA", +.br + "SRV", +.br + "TXT", +.br + "NAPTR", +.br + "A6", +.br + "CNAME", +.br + "SPF", +.br + "KEY", +.br + "DNSKEY", +.br + "HINFO", +.br + "WKS", +.br + "PX", +.br + "NSAP", +.br + ], +.br +); +.P +The maximum number of RR types allowed for this graph is 20. +.RE +.P +.BI BIND_SERVER_STATS_LIST +.RS +This is a two-dimensional array of counters about incoming request processing. The counters defined here will appear in the Server Statistics graph. +.P +our @BIND_SERVER_STATS_LIST = ( +.br + [ +.br + "Requestv4", +.br + "Requestv6", +.br + "ReqEdns0", +.br + "ReqBadEDNSVer", +.br + "ReqTSIG", +.br + "ReqSIG0", +.br + "ReqBadSIG", +.br + "ReqTCP", +.br + "Response", +.br + "QrySuccess", +.br + "QryAuthAns", +.br + "QryNoauthAns", +.br + "QryReferral", +.br + "QryNxrrset", +.br + "QrySERVFAIL", +.br + "QryNXDOMAIN", +.br + "QryRecursion", +.br + "QryDuplicate", +.br + "QryDropped", +.br + "QryFailure", +.br + ], +.br +); +.P +The maximum number of counters allowed for this graph is 20. +.RE +.P +.BI BIND_RESOLVER_STATS_LIST +.RS +This is a two-dimensional array of counters about name resolution performed in the internal resolver. The counters defined here will appear in the Resolver Statistics graph (_default view). +.P +our @BIND_RESOLVER_STATS_LIST = ( +.br + [ +.br + "Queryv4", +.br + "Queryv6", +.br + "Responsev4", +.br + "Responsev6", +.br + "NXDOMAIN", +.br + "SERVFAIL", +.br + "FORMERR", +.br + "OtherError", +.br + "EDNS0Fail", +.br + "Truncated", +.br + "Lame", +.br + "Retry", +.br + "QueryTimeout", +.br + "GlueFetchv4", +.br + "GlueFetchv6", +.br + "GlueFetchv4Fail", +.br + "GlueFetchv6Fail", +.br + "ValAttempt", +.br + "ValOk", +.br + "ValNegOk", +.br + ], +.br +); +.P +The maximum number of counters allowed for this graph is 20. +.RE +.P +.BI BIND_CACHE_RRSETS_LIST +.RS +This is a two-dimensional array of RR (Resource Records) types for each BIND server. The RR types defined here will appear in the Cache DB RRsets graph (_default view) which shows the number of RRsets per RR type (positive or negative) and nonexistent names stored in the cache database. +.P +our @BIND_CACHE_RRSETS_LIST = ( +.br + [ +.br + "A", +.br + "!A", +.br + "AAAA", +.br + "!AAAA", +.br + "DLV", +.br + "!DLV", +.br + "DS", +.br + "!DS", +.br + "MX", +.br + "NS", +.br + "CNAME", +.br + "!CNAME", +.br + "SOA", +.br + "!SOA", +.br + "!ANY", +.br + "PTR", +.br + "RRSIG", +.br + "NSEC", +.br + "DNSKEY", +.br + "NXDOMAIN", +.br + ], +.br +); +.P +The maximum number of RR types allowed for this graph is 20. +.RE +.SS NTP statistics (ntp.rrd) +This graph is able to monitor an unlimited number of NTP servers. +.P +.BI NTP_HOST_LIST +.RS +This is a list of NTP servers. +.P +WARNING: Every time the number of entries in this list changes, Monitorix will resize the \fIntp.rrd\fP file accordingly, removing all historical data. +.P +Default value: \fIlocalhost\fP +.RE +.P +.BI NTP_CODE_LIST +.RS +This is a two-dimensional array of group of Reference Identifier and Kiss-o'-Death Codes for every hostname specified in the \fBNTP_HOST_LIST\fP option. +.P +For more information on these NTP codes: +.br + +.br + +.P +our @NTP_CODE_LIST = ( +.br + [ +.br + "AUTH", +.br + "AUTO", +.br + "CRYP", +.br + "DENY", +.br + "GPS", +.br + "INIT", +.br + "NKEY", +.br + "RATE", +.br + "RMOT", +.br + "RSTR", +.br + ], +.br + [ +.br + "DENY", +.br + "RMOT", +.br + "RSTR", +.br + ], +.br +); +.P +The maximum number of codes allowed for each hostname is 10. +.RE +.SS Fail2ban statistics (fail2ban.rrd) +This graph is able to monitor an unlimited number of Fail2ban jails. +.P +.BI FAIL2BAN_PER_ROW +.RS +This is the number of fail2ban graphs that will be put in a row. +.P +Default value: \fI2\fP +.RE +.P +.BI FAIL2BAN_LIST +.RS +This is a two-dimensional array of unlimited group of jails defined in your Fail2ban configuration. For every group specified there is the ability to specify a description in the \fBFAIL2BAN_DESC\fP array. +.P +WARNING: Every time the number of entries in this list changes, Monitorix will resize the \fIfail2ban.rrd\fP file accordingly, removing all historical data. +.P +our @FAIL2BAN_LIST = ( +.br + [ +.br + "[apache]", +.br + "[apache-mod-security]", +.br + "[courierauth]", +.br + "[sshd]", +.br + "[pam-generic]", +.br + "[php-url-fopen]", +.br + "[vsftpd]", +.br + ], +.br + [ +.br + "[apache-imdbphp]", +.br + "[apache-evasive]", +.br + ], +.br +); +.P +The maximum number of jails allowed for each group is 9. +.RE +.P +.BI FAIL2BAN_DESC +.RS +This is the description of each group of jails in \fBFAIL2BAN_LIST\fP. Put one description for each group. An example would be: +.P +our @FAIL2BAN_DESC = ( +.br + "Security", +.br + "Overload / Abuse", +.br +); +.RE +.SS Icecast Streaming Media Server (icecast.rrd) +This graph is able to monitor an unlimited number of Icecast servers. +.P +.BI ICECAST_URL_LIST +.RS +This is a list of URLs of Icecast server status pages. +.P +WARNING: Every time the number of entries in this list changes, Monitorix will resize the \fIicecast.rrd\fP file accordingly, removing all historical data. +.P +Default value: \fIhttp://localhost:8000/status.xsl\fP +.RE +.P +.BI ICECAST_MP_LIST +.RS +This is a two-dimensional array of mountpoints configured for every URL specified in the \fBICECAST_URL_LIST\fP option. +.P +our @ICECAST_MP_LIST = ( +.br + [ +.br + "/stream1", +.br + "/stream2", +.br + "/stream3", +.br + ], +.br + [ +.br + "/stream1", +.br + "/stream2", +.br + ], +.br +); +.P +The maximum number of mountpoints allowed for each URL is 9. +.RE +.P +.BI ICECAST_GRAPH_MODE +.RS +This changes the layout of the listeners graph, the possible values are \fIR\fP for a real graph, or \fIS\fP for a stacked graph (every line or area is stacked on top of the previous element). +.P +Default value: \fIR\fP +.RE +.SS Devices interrupt activity (int.rrd) +Only the limit and rigid values may be set here. +.SS Monitoring remote servers (Multihost) +The \fIMultihost\fP feature allows you to monitor an unlimitted number of remote servers that already have Monitorix installed. +.P +Monitorix assumes that every remote server has been configured with the same settings in the \fIBASE_URL\fP and \fIBASE_CGI\fP options. Future versions may introduce the ability to have different configurations between local and remote servers. +.P +.BI MULTIHOST +.RS +This option enables the \fIMultihost\fP feature. +.P +Default value: \fIN\fP +.RE +.P +.BI MULTIHOST_FOOTER +.RS +If set to \fIY\fP Monitorix will show the original URL of each server at the bottom of the graph. Where security is important you may want to hide this information. +.P +Default value: \fIY\fP +.RE +.P +.BI MULTIHOST_IMGS_PER_ROW +.RS +If your horizontal screen resolution is pretty wide, you may want to increase the number of graphs that appear on each row. +.P +Default value: \fI2\fP +.RE +.P +.BI REMOTEHOST_LIST +.RS +This is a list of remote servers, with Monitorix already installed and working, that you plan to monitor from here. It consists of a series of name/value pairs with the right side being the URL or IP address and the left the server description. +.P +An example of this list would be: +.P +.RS +our @REMOTEHOST_LIST = ( +.br + "WWW Linux", "http://www.example.com", +.br + "Backup Linux", "http://192.168.1.4", +.br + "SMTP Linux", "http://71.16.11.2:8080", +.br +); +.RE +.P +As you can see all three entries use URLs to designate the location of each remote server. This means that each server most also have been installed on a CGI capable web server like Apache. +.RE +.P +.BI GROUPS +.RS +This enables the server grouping for those environments where there are too much servers to display at the same time. Hence, you can group them in order to show them separatedly. +.P +Default value: \fIN\fP +.RE +.P +.BI REMOTEGROUP_LIST +.RS +This is a list of groups of remote servers, with Monitorix already installed and working, that you plan to monitor from here. It consists of a series of name/value pairs with the right side being the names of the remote servers given in \fBREMOTEHOST_LIST\fP (separated by a colon) and in the left the group name. +.P +An example of this list would be: +.P +.RS +our @REMOTEGROUP_LIST = ( +.br + "My Group", "Backup Linux:SMTP Linux", +.br +); +.RE +.SS Monitoring the Internet traffic of LAN PCs, devices or whole networks +If your server acts as the gateway for a group of PCs, devices or even whole networks in your local LAN, you may want to know much Internet traffic each one is generating. +.P +This graph requires the \fIiptables\fP command on Linux systems, and the \fIipfw\fP command on FreeBSD and OpenBSD systems. +.P +The following are the options you will need to configure to accomplish all of this. +.P +.BI PC_LAN +.RS +This option enables this feature. +.P +Default value: \fIN\fP +.RE +.P +.BI PC_MAX +.RS +This is the number of LAN devices you want to monitor. There is no limit, but keep in mind that every time this number changes, Monitorix will resize its current \fIpc.rrd\fP file, removing all historical data. +.P +Default value: \fI10\fP +.RE +.P +.BI PC_IMGS_PER_ROW +.RS +If your horizontal screen resolution is pretty wide, you may want to increase the number of graphs that appear on each row. +.P +Default value: \fI2\fP +.RE +.P +.BI PC_LIST +.RS +This is the list of names of PCs, LAN devices or whole networks that you want to monitor. The only requirement is that all they must utilize this server as their gateway. +.P +If the names in this list are able to be resolved by a DNS query then you don't need to define the \fBPC_IP\fP list (below) with corresponding IP addresses. +.P +An example would be: +.P +.RS +our @PC_LIST = ( +.br + "pc8", +.br + "printer", +.br + "scanner", +.br + "lan3", +.br +); +.RE +.RE +.P +.BI PC_IP +.RS +This is the list of IP addresses and network masks corresponding to the entries defined in the \fBPC_LIST\fP. This list is only used when the those entries are not resolvable through a DNS query. +.P +An example would be: +.P +.RS +our @PC_IP = ( +.br + "192.168.1.108/32", +.br + "192.168.1.122/32", +.br + "192.168.1.203/32", +.br + "192.168.2.0/24", +.br +); +.RE +.RE +.P +.BI PC_ENABLE_MONTHLY_REPORTS +.RS +If this option is set to \fIY\fP, Monitorix will send a report of all the monthly Internet activity of the defined devices in \fBPC_LIST\fP to the specified email address on the first day of each month. +.P +Default value: \fIN\fP +.RE +.P +.BI PC_REPORT_LANG +.RS +Define here the language used in the monthly report. +.P +The possible values are: \fIca\fP, \fIde\fP, \fIen\fP, \fIit\fP and \fIpl\fP. +.P +Default value: \fIen\fP +.RE +.P +.BI PC_DEFAULT_MAIL +.RS +This is the default email address used to send the monthly reports. This option is only used if the \fBPC_REPORT_MAIL\fP array is empty. +.P +Default value: \fIroot@localhost\fP +.RE +.P +.BI PC_REPORT_MAIL +.RS +This is the list of email addresses (one per entry) that corresponds to each name listed in the \fBPC_LIST\fP array. If this list is empty then the \fBPC_DEFAULT_MAIL\fP option will be used as the default email address for all the PCs. +.P +An example would be: +.P +.RS +our @PC_MAIL = ( +.br + "user1@example.com", +.br + "user2@example.com", +.br + "user3@example.com", +.br + "admin@example.com", +.br +); +.RE +.RE +.SH AUTHOR +Monitorix is written by Jordi Sanfeliu +.SH COPYRIGHT +Copyright \(co 2005-2012 Jordi Sanfeliu +.br +Licensed under the GNU General Public License v2 (GPL). +.SH SEE ALSO +.BR monitorix (8), +.BR rrdtool (1) diff --git a/man/man8/monitorix.8 b/man/man8/monitorix.8 new file mode 100644 index 0000000..b3ea592 --- /dev/null +++ b/man/man8/monitorix.8 @@ -0,0 +1,57 @@ +.\" Monitorix manpage. +.\" Copyright (C) 2005-2012 by Jordi Sanfeliu +.\" +.\" This is the man page for the monitorix collector daemon. +.\" +.TH monitorix 8 "Sep 2012" 2.6.0 "Monitorix collector daemon" +.SH NAME +monitorix +.SH SYNOPSIS +\fBmonitorix\fR \fB-c configfile\fR [\fB-p pidfile\fR] [\fB-d none | graph[,graph] | all\fR] [\fB-v\fR] +.SH DESCRIPTION +This Perl daemon starts the main Monitorix process, which gathers statistics about the system it is running on and stores this information in a set of RRD files. +.SH OPTIONS +.TP +\fB\-c configfile\fR +The default location of the configuration file varies depending on the operating system: +.P +.RS +Linux: \fI/etc/monitorix.conf\fP +.br +FreeBSD: \fI/usr/local/etc/monitorix.conf\fP +.P +.RE +.TP +\fB\-p pidfile\fR +Stores the daemon's process ID into the specified file. +.TP +\fB\-d none | graph[,graph] | all\fR +Logs more information about what \fBmonitorix\fP is doing internally. The keys reflect if the data collected must be displayed on each case. If \fBall\fP is defined, the data collected of all enabled graphs will be shown. If \fBnone\fP is defined no data collected will be shown. Finally it is also possible to define a comma-separated list of graph names from which show their data collected. +.br +For a reference of all graph names check the option \fB@GRAPH_NAME\fP in the \fImonitorix.conf\fP configuration file. +.TP +\fB\-v\fR +Displays version information. +.SH SIGNALS +On receipt of a SIGHUP, \fBmonitorix\fP will close and reopen its log file. This is useful in scripts which rotate and age log files. +.P +Note that the configuration file is not re-read. I plan to change this in future versions. +.SH FILES +The following is the set of the special files created on every startup: +.TP 41 +\fB$BASE_DIR/cgi-bin/monitorix.conf.path\fP +stores the path of \fIconfigfile\fP. +.TP 41 +\fB$BASE_DIR/cgi-bin/monitorix.hplog\fP +stores the output of \fIhplog\fP. +.TP 41 +\fB$BASE_DIR/index.html\fP +HTML main page. +.SH AUTHOR +Monitorix is written by Jordi Sanfeliu +.SH COPYRIGHT +Copyright \(co 2005-2012 Jordi Sanfeliu +.br +Licensed under the GNU General Public License v2 (GPL). +.SH "SEE ALSO" +.BR monitorix.conf (5) diff --git a/monitorix b/monitorix new file mode 100755 index 0000000..48224ac --- /dev/null +++ b/monitorix @@ -0,0 +1,7005 @@ +#!/usr/bin/env perl +# +# Monitorix - A lightweight system monitoring tool. +# +# Copyright (C) 2005-2012 by Jordi Sanfeliu +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +require 5.006; + +no strict "vars"; +no warnings "once"; +#use warnings; +use RRDs; +use POSIX; +use File::Basename; +use LWP::UserAgent; +use XML::Simple; +use Socket; +use DBI; +use Getopt::Std; +use Cwd 'abs_path'; +use locale; + +# Force a standard locale +$ENV{LANG} = ""; +setlocale(LC_TIME, "C"); + +# Signals to Trap and Handle +$SIG{'INT' } = 'INT_handler'; +$SIG{'ABRT'} = 'INT_handler'; +$SIG{'QUIT'} = 'INT_handler'; +$SIG{'TRAP'} = 'INT_handler'; +$SIG{'STOP'} = 'INT_handler'; +$SIG{'TERM'} = 'INT_handler'; +$SIG{'CHLD'} = 'CHLD_handler'; +$SIG{'HUP' } = 'HUP_handler'; +$SIG{'ALRM'} = 'ALRM_handler'; + +use constant VERSION => "2.6.0"; +use constant RELDATE => "19-Sep-2012"; + +my @suppsys = ("Linux", "FreeBSD", "OpenBSD", "NetBSD"); +my @graphs; +my @graphs_debug; +my $os; +my $kernel_branch; + +sub INT_handler { + my ($signal) = @_; + + logger("SIG$signal caught."); + flush_accounting_rules(); + logger("Exiting."); + exit(0); +} + +sub CHLD_handler { + my $pid = waitpid(-1, WNOHANG); +} + +sub HUP_handler { + my ($signal) = @_; + my $myself = (caller(0))[3]; + + logger("SIG$signal caught."); + close(STDOUT); + close(STDERR); + unless(open(STDOUT, ">> $LOG_FILE")) { + logger("Can't write to LOG: $!"); + } + unless(open(STDERR, ">> $LOG_FILE")) { # >>&STDOUT XXX + logger("Can't write to LOG: $!"); + } + logger("$myself: reopening log file."); +} + +sub ALRM_handler { + my $myself = (caller(0))[3]; + my ($sec, $min, $hour, $mday) = localtime(time); + + if($sec == 0) { + foreach my $g (@graphs) { + my ($t) = split('_', $g); + logger("$myself: calling $g()") unless !$opt_d; + if(!grep {$_ eq $t} (@graphs_debug)) { + undef($t); + } + eval {&$g($t);}; + if($@) { + logger("$g(): $@"); + } + } + if($PC_LAN eq "Y" && $PC_ENABLE_MONTHLY_REPORTS eq "Y") { + if($min == 0 && $hour == 0) { + get_counters(); + if($mday == 1) { + send_reports(); + } + } + } + } + alarm(1); +} + +sub logger { + my ($msg) = @_; + + $msg = localtime() . " - " . $msg; + print("$msg\n"); +} + +sub daemonize { + if(fork) { + exit(0); # parent exits + } + + setsid(); + foreach(0 .. (sysconf(&POSIX::_SC_OPEN_MAX) || 1024)) { + close($_); + } + unless(chdir("/")) { + die("Can't chdir to /: $!"); + } + unless(umask(022)) { + die("Unable to umask 022: $!"); + } +# unless(open(STDIN, "< /dev/null")) { +# die("Can't read /dev/null: $!"); +# } + unless(open(STDOUT, ">> $LOG_FILE")) { + die("Can't write to LOG: $!"); + } + unless(open(STDERR, ">> $LOG_FILE")) { # >>&STDOUT XXX + die("Can't write to LOG: $!"); + } +} + +sub usage { + print(STDERR << "EOF"); +Usage: monitorix -c configfile [-p pidfile] [-d none | graph[,graph] | all ] [-v] + +EOF + exit(1); +} + +sub create_index { + my $myself = (caller(0))[3]; + + my $n; + my $gname; + my %rgraphs = reverse %GRAPHS; + + if($THEME_COLOR eq "black") { + $bgcolor = $BLACK{main_bg}; + $table_back_color = $BLACK{graph_bg}; + $title_back_color = $BLACK{title_bg}; + $title_fore_color = $BLACK{title_fg}; + } elsif(!$THEME_COLOR || $THEME_COLOR eq "white") { + $bgcolor = "#ffffff"; + $table_back_color = "#CCCCCC"; + $title_back_color = "#777777"; + $title_fore_color = "#CCCC00"; + } else { + logger("$myself: ERROR: invalid value in \$THEME_COLOR") unless !$opt_d; + } + + if(!open(OUT, "> $BASE_DIR/index.html")) { + die "unable to create ${BASE_DIR}index.html. $!"; + } + print(OUT < + + + $TITLE + + + +
+

+
+ + + + + + + + +
+ +
+

v@{[VERSION]}

+
+

+

+ + + + + + +EOF + + if(!$FAVICON) { + logger("WARNING: the option \$FAVICON is missing in your configuration file. Do you really have the latest version?"); + } + print(OUT " \n"); + + + + print(OUT " \n"); + + + print(OUT < +
+ + Hostname  + + + + Graph  + +
\n"); + print(OUT " \n"); + print(OUT " \n"); + print(OUT " \n"); + print(OUT "
+

+ + + + + + + +
+ + Daily  + + + Weekly  + + + Monthly  + + + Yearly  +
+

+ + +

+
+
+ + +EOF + close(OUT); +} + +sub flush_accounting_rules { + my $num = 0; + + # flushes out any Monitorix iptables/ipfw rules + if($os eq "Linux") { + logger("Flushing out iptables rules.") unless !$opt_d; + if(open(IN, "iptables -nxvL INPUT --line-numbers |")) { + my @rules; + my @names; + while() { + my ($rule, undef, undef, $name) = split(' ', $_); + if($name =~ /MONITORIX_IN/ || /NGINX_IN/) { + push(@rules, $rule); + push(@names, $name); + } + } + close(IN); + @rules = reverse(@rules); + foreach(@rules) { + system("iptables -D INPUT $_"); + $num++; + } + foreach(@names) { + system("iptables -X $_"); + } + } + if(open(IN, "iptables -nxvL OUTPUT --line-numbers |")) { + my @rules; + my @names; + while() { + my ($rule, undef, undef, $name) = split(' ', $_); + if($name =~ /MONITORIX_OUT/ || /NGINX_OUT/) { + push(@rules, $rule); + push(@names, $name); + } + } + close(IN); + @rules = reverse(@rules); + foreach(@rules) { + system("iptables -D OUTPUT $_"); + $num++; + } + foreach(@names) { + system("iptables -X $_"); + } + } + logger("$num iptables rules have been flushed.") unless !$opt_d; + } + if($os eq "FreeBSD" || $os eq "OpenBSD") { + logger("Flushing out ipfw rules.") unless !$opt_d; + system("ipfw delete $PORT_RULE 2>/dev/null"); + system("ipfw delete $NGINX_RULE 2>/dev/null"); + } +} + +# SYSTEM graph +# ---------------------------------------------------------------------------- +sub system_init { + my $myself = (caller(0))[3]; + + if(!(-e $SYSTEM_RRD)) { + logger("Creating '$SYSTEM_RRD' file."); + eval { + RRDs::create($SYSTEM_RRD, + "--step=60", + "DS:system_load1:GAUGE:120:0:U", + "DS:system_load5:GAUGE:120:0:U", + "DS:system_load15:GAUGE:120:0:U", + "DS:system_nproc:GAUGE:120:0:U", + "DS:system_npslp:GAUGE:120:0:U", + "DS:system_nprun:GAUGE:120:0:U", + "DS:system_npwio:GAUGE:120:0:U", + "DS:system_npzom:GAUGE:120:0:U", + "DS:system_npstp:GAUGE:120:0:U", + "DS:system_npswp:GAUGE:120:0:U", + "DS:system_mtotl:GAUGE:120:0:U", + "DS:system_mbuff:GAUGE:120:0:U", + "DS:system_mcach:GAUGE:120:0:U", + "DS:system_mfree:GAUGE:120:0:U", + "DS:system_macti:GAUGE:120:0:U", + "DS:system_minac:GAUGE:120:0:U", + "DS:system_val01:GAUGE:120:0:U", + "DS:system_val02:GAUGE:120:0:U", + "DS:system_val03:GAUGE:120:0:U", + "DS:system_val04:GAUGE:120:0:U", + "DS:system_val05:GAUGE:120:0:U", + "RRA:AVERAGE:0.5:1:1440", + "RRA:AVERAGE:0.5:30:336", + "RRA:AVERAGE:0.5:60:744", + "RRA:AVERAGE:0.5:1440:365", + "RRA:MIN:0.5:1:1440", + "RRA:MIN:0.5:30:336", + "RRA:MIN:0.5:60:744", + "RRA:MIN:0.5:1440:365", + "RRA:MAX:0.5:1:1440", + "RRA:MAX:0.5:30:336", + "RRA:MAX:0.5:60:744", + "RRA:MAX:0.5:1440:365", + "RRA:LAST:0.5:1:1440", + "RRA:LAST:0.5:30:336", + "RRA:LAST:0.5:60:744", + "RRA:LAST:0.5:1440:365", + ); + }; + my $err = RRDs::error; + if($@ || $err) { + logger("$@") unless !$@; + if($err) { + logger("ERROR: while creating $SYSTEM_RRD: $err"); + if($err eq "RRDs::error") { + logger("... is the RRDtool Perl package installed?"); + } + } + return; + } + } + + if($ENABLE_ALERTS eq "Y") { + if(! -x $ALERT_LOADAVG_SCRIPT) { + logger("$myself: ERROR: script '$ALERT_LOADAVG_SCRIPT' doesn't exist or don't has execute permissions."); + } + } + + our $system_hist = 0; + push(@graphs, "system_update"); + if($opt_d eq "all" || $debug) { + logger("$myself: Ok"); + } +} + +sub system_update { + my $myself = (caller(0))[3]; + my ($debug) = @_; + + my $load1; + my $load5; + my $load15; + my $nproc; + my $npslp; + my $nprun; + my $npwio; + my $npzom; + my $npstp; + my $npswp; + my $mtotl; + my $mbuff; + my $mcach; + my $mfree; + my $macti; + my $minac; + my $val01 = 0; + my $val02 = 0; + my $val03 = 0; + my $val04 = 0; + my $val05 = 0; + + my $rrdata = "N"; + + $npwio = $npzom = $npstp = $npswp = 0; + + if($os eq "Linux") { + open(IN, "/proc/loadavg"); + while() { + if(/^(\d+\.\d+) (\d+\.\d+) (\d+\.\d+) (\d+)\/(\d+)/) { + $load1 = $1; + $load5 = $2; + $load15 = $3; + $nprun = $4; + $npslp = $5; + } + } + close(IN); + $nproc = $npslp + $nprun; + + open(IN, "/proc/meminfo"); + while() { + if(/^MemTotal:\s+(\d+) kB$/) { + $mtotl = $1; + next; + } + if(/^MemFree:\s+(\d+) kB$/) { + $mfree = $1; + next; + } + if(/^Buffers:\s+(\d+) kB$/) { + $mbuff = $1; + next; + } + if(/^Cached:\s+(\d+) kB$/) { + $mcach = $1; + last; + } + } + close(IN); + $macti = $minac = ""; + } elsif($os eq "FreeBSD") { + my $page_size; + open(IN, "sysctl -n vm.loadavg |"); + while() { + if(/^\{ (\d+\.\d+) (\d+\.\d+) (\d+\.\d+) \}$/) { + $load1 = $1; + $load5 = $2; + $load15 = $3; + } + } + close(IN); + open(IN, "sysctl vm.vmtotal |"); + while() { + if(/^Processes:\s+\(RUNQ:\s+(\d+) Disk.*? Sleep:\s+(\d+)\)$/) { + $nprun = $1; + $npslp = $2; + } + if(/^Free Memory Pages:\s+(\d+)K$/) { + $mfree = $1; + } + } + close(IN); + $nproc = $npslp + $nprun; + $mtotl = `sysctl -n hw.realmem`; + $mbuff = `sysctl -n vfs.bufspace`; + $mcach = `sysctl -n vm.stats.vm.v_cache_count`; + + chomp($mbuff); + $mbuff = $mbuff / 1024; + chomp($mtotl); + $mtotl = $mtotl / 1024; + $page_size = `sysctl -n vm.stats.vm.v_page_size`; + $macti = `sysctl -n vm.stats.vm.v_active_count`; + $minac = `sysctl -n vm.stats.vm.v_inactive_count`; + chomp($page_size, $mcach, $macti, $minac); + $mcach = ($page_size * $mcach) / 1024; + $macti = ($page_size * $macti) / 1024; + $minac = ($page_size * $minac) / 1024; + } elsif($os eq "OpenBSD" || $os eq "NetBSD") { + open(IN, "sysctl -n vm.loadavg |"); + while() { + if(/^(\d+\.\d+) (\d+\.\d+) (\d+\.\d+)$/) { + $load1 = $1; + $load5 = $2; + $load15 = $3; + } + } + close(IN); + open(IN, "top -b |"); + while() { + if(/ processes:/) { + $_ =~ s/:/,/; + my (@tmp) = split(',', $_); + foreach(@tmp) { + my ($num, $desc) = split(' ', $_); + $nproc = $num unless $desc ne "processes"; + if(grep {$_ eq $desc} ("idle", "sleeping", "stopped", "zombie")) { + $npslp += $num; + } + if($desc eq "running" || $desc eq "on") { + $nprun += $num; + } + } + } + if($os eq "OpenBSD") { + if(/^Memory: Real: (\d+)\w\/\d+\w act\/tot Free: (\d+)\w /) { + $macti = $1; + $mfree = $2; + $macti = int($macti) * 1024; + $mfree = int($mfree) * 1024; + last; + } + } + if($os eq "NetBSD") { + if(/^Memory: (\d+)\w Act, .*, (\d+)\w Free/) { + $macti = $1; + $mfree = $2; + $macti = int($macti) * 1024; + $mfree = int($mfree) * 1024; + last; + } + } + } + close(IN); + $mtotl = `sysctl -n hw.physmem`; + chomp($mtotl); + $mtotl = $mtotl / 1024; + } + + chomp( + $load1, + $load5, + $load15, + $nproc, + $npslp, + $nprun, + $npwio, + $npzom, + $npstp, + $npswp, + $mtotl, + $mbuff, + $mcach, + $mfree, + $macti, + $minac, + ); + + # SYSTEM alert + if($ENABLE_ALERTS eq "Y") { + if(!$ALERT_LOADAVG_THRESHOLD || $load15 < $ALERT_LOADAVG_THRESHOLD) { + $system_hist = 0; + } else { + if(!$system_hist) { + $system_hist = time; + } + if($system_hist > 0 && (time - $system_hist) > $ALERT_LOADAVG_TIMEINTVL) { + if(-x $ALERT_LOADAVG_SCRIPT) { + system($ALERT_LOADAVG_SCRIPT . " " .$ALERT_LOADAVG_TIMEINTVL . " " . $ALERT_LOADAVG_THRESHOLD . " " . $load15); + } + $system_hist = time; + } + } + } + + $rrdata .= ":$load1:$load5:$load15:$nproc:$npslp:$nprun:$npwio:$npzom:$npstp:$npswp:$mtotl:$mbuff:$mcach:$mfree:$macti:$minac:$val01:$val02:$val03:$val04:$val05"; + RRDs::update($SYSTEM_RRD, $rrdata); + if($opt_d eq "all" || $debug) { + logger("$myself: $rrdata"); + } + my $err = RRDs::error; + logger("ERROR: while updating $SYSTEM_RRD: $err") if $err; +} + +# KERN graph +# ---------------------------------------------------------------------------- +sub kern_init { + my $myself = (caller(0))[3]; + + if(!(-e $KERN_RRD)) { + logger("Creating '$KERN_RRD' file."); + eval { + RRDs::create($KERN_RRD, + "--step=60", + "DS:kern_user:GAUGE:120:0:100", + "DS:kern_nice:GAUGE:120:0:100", + "DS:kern_sys:GAUGE:120:0:100", + "DS:kern_idle:GAUGE:120:0:100", + "DS:kern_iow:GAUGE:120:0:100", + "DS:kern_irq:GAUGE:120:0:100", + "DS:kern_sirq:GAUGE:120:0:100", + "DS:kern_steal:GAUGE:120:0:100", + "DS:kern_guest:GAUGE:120:0:100", + "DS:kern_cs:COUNTER:120:0:U", + "DS:kern_dentry:GAUGE:120:0:100", + "DS:kern_file:GAUGE:120:0:100", + "DS:kern_inode:GAUGE:120:0:100", + "DS:kern_forks:COUNTER:120:0:U", + "DS:kern_vforks:COUNTER:120:0:U", + "DS:kern_val03:GAUGE:120:0:100", + "DS:kern_val04:GAUGE:120:0:100", + "DS:kern_val05:GAUGE:120:0:100", + "RRA:AVERAGE:0.5:1:1440", + "RRA:AVERAGE:0.5:30:336", + "RRA:AVERAGE:0.5:60:744", + "RRA:AVERAGE:0.5:1440:365", + "RRA:MIN:0.5:1:1440", + "RRA:MIN:0.5:30:336", + "RRA:MIN:0.5:60:744", + "RRA:MIN:0.5:1440:365", + "RRA:MAX:0.5:1:1440", + "RRA:MAX:0.5:30:336", + "RRA:MAX:0.5:60:744", + "RRA:MAX:0.5:1440:365", + "RRA:LAST:0.5:1:1440", + "RRA:LAST:0.5:30:336", + "RRA:LAST:0.5:60:744", + "RRA:LAST:0.5:1440:365", + ); + }; + my $err = RRDs::error; + if($@ || $err) { + logger("$@") unless !$@; + if($err) { + logger("ERROR: while creating $KERN_RRD: $err"); + if($err eq "RRDs::error") { + logger("... is the RRDtool Perl package installed?"); + } + } + return; + } + } + + # Since 2.2.0 two new values are used (kern_val01 and kern_val02) to + # support 'forks' and 'vforks'. These two values need to be converted + # to COUNTER and renamed. + RRDs::tune($KERN_RRD, + "--data-source-rename=kern_val01:kern_forks", + "--data-source-type=kern_forks:COUNTER", + "--maximum=kern_forks:U", + ); + RRDs::tune($KERN_RRD, + "--data-source-rename=kern_val02:kern_vforks", + "--data-source-type=kern_vforks:COUNTER", + "--maximum=kern_vforks:U", + ); + + our %kernel_hist = (); + push(@graphs, "kern_update"); + if($opt_d eq "all" || $debug) { + logger("$myself: Ok"); + } +} + +sub kern_update { + my $myself = (caller(0))[3]; + my ($debug) = @_; + + my $user; + my $nice; + my $sys; + my $idle; + my $iow; + my $irq; + my $sirq; + my $steal; + my $guest; + my $cs; + my $dentry; + my $file; + my $inode; + my $forks; + my $vforks = 0; + my $val03 = 0; + my $val04 = 0; + my $val05 = 0; + + my $lastuser = 0; + my $lastnice = 0; + my $lastsys = 0; + my $lastidle = 0; + my $lastiow = 0; + my $lastirq = 0; + my $lastsirq = 0; + my $laststeal = 0; + my $lastguest = 0; + + my $rrdata = "N"; + + if($kernel_hist{'kernel'}) { + (undef, $lastuser, $lastnice, $lastsys, $lastidle, $lastiow, $lastirq, $lastsirq, $laststeal, $lastguest) = split(' ', $kernel_hist{'kernel'}); + } + + if($os eq "Linux") { + open(IN, "/proc/stat"); + while() { + if(/^cpu /) { + (undef, $user, $nice, $sys, $idle, $iow, $irq, $sirq, $steal, $guest) = split(' ', $_); + $kernel_hist{'kernel'} = $_; + next; + } + if(/^ctxt (\d+)$/) { + # avoid initial spike + $cs = int($1) unless !$kernel_hist{'cs'}; + $kernel_hist{'cs'} = int($1) unless $kernel_hist{'cs'}; + next; + } + if(/^processes (\d+)$/) { + # avoid initial spike + $forks = int($1) unless !$kernel_hist{'forks'}; + $kernel_hist{'forks'} = int($1) unless $kernel_hist{'forks'}; + $vforks = 0; + last; + } + } + close(IN); + open(IN, "/proc/sys/fs/dentry-state"); + while() { + if(/^(\d+)\s+(\d+)\s+/) { + $dentry = ($1 * 100) / ($1 + $2); + } + } + close(IN); + open(IN, "/proc/sys/fs/file-nr"); + while() { + if(/^(\d+)\s+\d+\s+(\d+)$/) { + $file = ($1 * 100) / $2; + } + } + close(IN); + open(IN, "/proc/sys/fs/inode-nr"); + while() { + if(/^(\d+)\s+(\d+)$/) { + $inode = ($1 * 100) / ($1 + $2); + } + } + close(IN); + } elsif($os eq "FreeBSD") { + my $max; + my $num; + my $data; + + my $cptime = `sysctl -n kern.cp_time`; + chomp($cptime); + my @tmp = split(' ', $cptime); + ($user, $nice, $sys, $iow, $idle) = @tmp; + + $kernel_hist{'kernel'} = join(' ', "cpu", $user, $nice, $sys, $idle, $iow); + $data = `sysctl -n vm.stats.sys.v_swtch`; + chomp($data); + $cs = int($data) unless !$kernel_hist{'cs'}; + $kernel_hist{'cs'} = int($data) unless $kernel_hist{'cs'}; + + $data = `sysctl -n vm.stats.vm.v_forks`; + chomp($data); + $forks = int($data) unless !$kernel_hist{'forks'}; + $kernel_hist{'forks'} = int($data) unless $kernel_hist{'forks'}; + + $data = `sysctl -n vm.stats.vm.v_vforks`; + chomp($data); + $vforks = int($data) unless !$kernel_hist{'vforks'}; + $kernel_hist{'vforks'} = int($data) unless $kernel_hist{'vforks'}; + + $max = `sysctl -n kern.maxfiles`; + chomp($max); + $num = `sysctl -n kern.openfiles`; + chomp($num); + $file = ($num * 100) / $max; + + $max = `sysctl -n kern.maxvnodes`; + chomp($max); + $num = `sysctl -n vfs.numvnodes`; + chomp($num); + $inode = ($num * 100) / $max; + } elsif($os eq "OpenBSD") { + my $max; + my $num; + my $data; + + my $cptime = `sysctl -n kern.cp_time`; + chomp($cptime); + my @tmp = split(',', $cptime); + ($user, $nice, $sys, $iow, $idle) = @tmp; + $kernel_hist{'kernel'} = join(' ', "cpu", $user, $nice, $sys, $idle, $iow); + open(IN, "vmstat -s |"); + while() { + if(/^\s*(\d+) cpu context switches$/) { + $cs = int($1) unless !$kernel_hist{'cs'}; + $kernel_hist{'cs'} = int($1) unless $kernel_hist{'cs'}; + last; + } + } + close(IN); + + $data = `sysctl -n kern.forkstat.forks`; + chomp($data); + $forks = int($data) unless !$kernel_hist{'forks'}; + $kernel_hist{'forks'} = int($data) unless $kernel_hist{'forks'}; + + $data = `sysctl -n kern.forkstat.vforks`; + chomp($data); + $vforks = int($data) unless !$kernel_hist{'vforks'}; + $kernel_hist{'vforks'} = int($data) unless $kernel_hist{'vforks'}; + + $max = `sysctl -n kern.maxfiles`; + chomp($max); + $num = `sysctl -n kern.nfiles`; + chomp($num); + $file = ($num * 100) / $max; + + $max = `sysctl -n kern.maxvnodes`; + chomp($max); + $data = `sysctl -n kern.malloc.kmemstat.vnodes`; + ($num) = ($data =~ m/^\(inuse = (\d+), /); + $inode = ($num * 100) / $max; + } elsif($os eq "NetBSD") { + my $max; + my $num; + my $data; + + my $cptime = `sysctl -n kern.cp_time`; + chomp($cptime); + my @tmp = ($cptime =~ m/user = (\d+), nice = (\d+), sys = (\d+), intr = (\d+), idle = (\d+)/); + ($user, $nice, $sys, $iow, $idle) = @tmp; + $kernel_hist{'kernel'} = join(' ', "cpu", $user, $nice, $sys, $idle, $iow); + open(IN, "vmstat -s |"); + while() { + if(/^\s*(\d+) CPU context switches$/) { + $cs = int($1) unless !$kernel_hist{'cs'}; + $kernel_hist{'cs'} = int($1) unless $kernel_hist{'cs'}; + next; + } + if(/^\s*(\d+) forks total$/) { + $forks = int($1) unless !$kernel_hist{'forks'}; + $kernel_hist{'forks'} = int($1) unless $kernel_hist{'forks'}; + next; + } + } + close(IN); + + $vforks = 0; + + open(IN, "pstat -T |"); + while() { + if(/^(\d+)\/(\d+) files$/) { + $file = ($1 * 100) / $2; + } + } + close(IN); + + $inode = 0; + } + + # Linux 2.4, early Linux 2.6 versions and other systems don't have + # these values. + $iow = 0 unless $iow; + $irq = 0 unless $irq; + $sirq = 0 unless $sirq; + $steal = 0 unless $sirq; + $guest = 0 unless $guest; + $lastiow = 0 unless $lastiow; + $lastirq = 0 unless $lastirq; + $lastsirq = 0 unless $lastsirq; + $laststeal = 0 unless $lastsirq; + $lastguest = 0 unless $lastguest; + + if($user >= $lastuser && $nice >= $lastnice && $sys >= $lastsys && $idle >= $lastidle && $iow >= $lastiow && $irq >= $lastirq && $sirq >= $lastsirq && $steal >= $laststeal && $guest >= $lastguest) { + my $user_ = $user - $lastuser; + my $nice_ = $nice - $lastnice; + my $sys_ = $sys - $lastsys; + my $idle_ = $idle - $lastidle; + my $iow_ = $iow - $lastiow; + my $irq_ = $irq - $lastirq; + my $sirq_ = $sirq - $lastsirq; + my $steal_ = $steal - $laststeal; + my $guest_ = $guest - $lastguest; + my $total = $user_ + $nice_ + $sys_ + $idle_ + $iow_ + $irq_ + $sirq_ + $steal_ + $guest_; + $user = ($user_ * 100) / $total; + $nice = ($nice_ * 100) / $total; + $sys = ($sys_ * 100) / $total; + $idle = ($idle_ * 100) / $total; + $iow = ($iow_ * 100) / $total; + $irq = ($irq_ * 100) / $total; + $sirq = ($sirq_ * 100) / $total; + $steal = ($steal_ * 100) / $total; + $guest = ($guest_ * 100) / $total; + } else { + $user = "nan"; + $nice = "nan"; + $sys = "nan"; + $idle = "nan"; + $iow = "nan"; + $irq = "nan"; + $sirq = "nan"; + $steal = "nan"; + $guest = "nan"; + } + + $rrdata .= ":$user:$nice:$sys:$idle:$iow:$irq:$sirq:$steal:$guest:$cs:$dentry:$file:$inode:$forks:$vforks:$val03:$val04:$val05"; + RRDs::update($KERN_RRD, $rrdata); + if($opt_d eq "all" || $debug) { + logger("$myself: $rrdata"); + } + my $err = RRDs::error; + logger("ERROR: while updating $KERN_RRD: $err") if $err; +} + +# PROC graph +# ---------------------------------------------------------------------------- +sub proc_init { + my $myself = (caller(0))[3]; + + my $info; + my @ds; + my @tmp; + my $n; + + if(!grep {$_ eq $os} ("Linux", "FreeBSD")) { + logger("$myself is not supported yet by your operating system ($os)."); + return; + } + + if(-e $PROC_RRD) { + $info = RRDs::info($PROC_RRD); + for my $key (keys %$info) { + if(index($key, 'ds[') == 0) { + if(index($key, '.type') != -1) { +# print("$key\n"); + push(@ds, substr($key, 3, index($key, ']') - 3)); + } + } + } +# foreach(@ds) { +# print($_ . "\n"); +# } +# print(scalar(@ds) . "\n"); + if(scalar(@ds) / 9 != $PROC_MAX) { + logger("Detected size mismatch between \$PROC_MAX ($PROC_MAX) and $PROC_RRD (" . scalar(@ds) / 9 . "). Resizing it accordingly. All historic data will be lost. Backup file created."); + rename($PROC_RRD, "$PROC_RRD.bak"); + } + } + + if(!(-e $PROC_RRD)) { + logger("Creating '$PROC_RRD' file."); + for($n = 0; $n < $PROC_MAX; $n++) { + push(@tmp, "DS:proc" . $n . "_user:GAUGE:120:0:100"); + push(@tmp, "DS:proc" . $n . "_nice:GAUGE:120:0:100"); + push(@tmp, "DS:proc" . $n . "_sys:GAUGE:120:0:100"); + push(@tmp, "DS:proc" . $n . "_idle:GAUGE:120:0:100"); + push(@tmp, "DS:proc" . $n . "_iow:GAUGE:120:0:100"); + push(@tmp, "DS:proc" . $n . "_irq:GAUGE:120:0:100"); + push(@tmp, "DS:proc" . $n . "_sirq:GAUGE:120:0:100"); + push(@tmp, "DS:proc" . $n . "_steal:GAUGE:120:0:100"); + push(@tmp, "DS:proc" . $n . "_guest:GAUGE:120:0:100"); + } + eval { + RRDs::create($PROC_RRD, + "--step=60", + @tmp, + "RRA:AVERAGE:0.5:1:1440", + "RRA:AVERAGE:0.5:30:336", + "RRA:AVERAGE:0.5:60:744", + "RRA:AVERAGE:0.5:1440:365", + "RRA:MIN:0.5:1:1440", + "RRA:MIN:0.5:30:336", + "RRA:MIN:0.5:60:744", + "RRA:MIN:0.5:1440:365", + "RRA:MAX:0.5:1:1440", + "RRA:MAX:0.5:30:336", + "RRA:MAX:0.5:60:744", + "RRA:MAX:0.5:1440:365", + "RRA:LAST:0.5:1:1440", + "RRA:LAST:0.5:30:336", + "RRA:LAST:0.5:60:744", + "RRA:LAST:0.5:1440:365", + ); + }; + my $err = RRDs::error; + if($@ || $err) { + logger("$@") unless !$@; + if($err) { + logger("ERROR: while creating $PROC_RRD: $err"); + if($err eq "RRDs::error") { + logger("... is the RRDtool Perl package installed?"); + } + } + return; + } + } + + our %proc_hist = (); + push(@graphs, "proc_update"); + if($opt_d eq "all" || $debug) { + logger("$myself: Ok"); + } +} + +sub proc_update { + my $myself = (caller(0))[3]; + my ($debug) = @_; + + my @proc; + my $total; + + my $n; + my @lastproc; + + my @p; + my @l; + my $rrdata = "N"; + + # Read last processor usage data + my $str; + for($n = 0; $n < $PROC_MAX; $n++) { + $str = "cpu" . $n; + if($proc_hist{$str}) { + push(@lastproc, $proc_hist{$str}); + } + } + + if($os eq "Linux") { + open(IN, "/proc/stat"); + while() { + for($n = 0; $n < $PROC_MAX; $n++) { + $str = "cpu" . $n; + if(/^cpu$n /) { + $proc_hist{$str} = $_; + chomp($proc_hist{$str}); + push(@proc, $proc_hist{$str}); + } + } + } + close(IN); + } elsif($os eq "FreeBSD") { + my $cptimes; + my @tmp; + my $from; + my $to; + my $ncpu = `sysctl -n hw.ncpu`; + open(IN, "sysctl -n kern.cp_times |"); + my @data = split(' ', ); + close(IN); + chomp($ncpu); + for($n = 0; $n < $PROC_MAX; $n++) { + $str = "cpu" . $n; + $from = $n * 5; + $to = $from + 4; + @tmp = @data[$from..$to]; + @tmp[0, 1, 2, 3, 4] = @tmp[0, 1, 2, 4, 3]; + $cptimes = join(' ', @tmp); + chomp($cptimes); + $cptimes = $str . " " . $cptimes; + $proc_hist{$str} = $cptimes; + push(@proc, $cptimes); + } + } + + my @deltas; + for($n = 0; $n < $PROC_MAX; $n++) { + if($proc[$n]) { + @p = split(' ', $proc[$n]); + @l = split(' ', $lastproc[$n]); + @deltas = ( + $p[1] - $l[1], # user + $p[2] - $l[2], # nice + $p[3] - $l[3], # sys + $p[4] - $l[4], # idle + $p[5] - $l[5], # iow + $p[6] - $l[6], # irq + $p[7] - $l[7], # sirq + $p[8] - $l[8], # steal + $p[9] - $l[9], # guest + ); + $total = $deltas[0] + $deltas[1] + $deltas[2] + $deltas[3] + $deltas[4] + $deltas[5] + $deltas[6] + $deltas[7] + $deltas[8]; + + undef(@p); + push(@p, $deltas[0] ? ($deltas[0] * 100) / $total : 0); + push(@p, $deltas[1] ? ($deltas[1] * 100) / $total : 0); + push(@p, $deltas[2] ? ($deltas[2] * 100) / $total : 0); + push(@p, $deltas[3] ? ($deltas[3] * 100) / $total : 0); + push(@p, $deltas[4] ? ($deltas[4] * 100) / $total : 0); + push(@p, $deltas[5] ? ($deltas[5] * 100) / $total : 0); + push(@p, $deltas[6] ? ($deltas[6] * 100) / $total : 0); + push(@p, $deltas[7] ? ($deltas[7] * 100) / $total : 0); + push(@p, $deltas[8] ? ($deltas[8] * 100) / $total : 0); + $proc[$n] = join(' ', @p); + } else { + $proc[$n] = join(' ', (0, 0, 0, 0, 0, 0, 0, 0, 0)); + } + } + + for($n = 0; $n < $PROC_MAX; $n++) { + @p = split(' ', $proc[$n]); + $rrdata .= ":$p[0]:$p[1]:$p[2]:$p[3]:$p[4]:$p[5]:$p[6]:$p[7]:$p[8]"; + } + RRDs::update($PROC_RRD, $rrdata); + if($opt_d eq "all" || $debug) { + logger("$myself: $rrdata"); + } + my $err = RRDs::error; + logger("ERROR: while updating $PROC_RRD: $err") if $err; +} + +# HPTEMP graph +# ---------------------------------------------------------------------------- +sub hptemp_init { + my $myself = (caller(0))[3]; + + # save the contents of 'hplog -t' since only 'root' is able to run it + # it also checks if 'hplog' does exists. + if(!open(IN, "hplog -t |")) { + logger("$myself: unable to execute 'hplog'. $!"); + return; + } + my @data = ; + close(IN); + open(OUT, "> $BASE_DIR/cgi-bin/monitorix.hplog"); + print(OUT @data); + close(OUT); + + if(!(-e $HPTEMP_RRD)) { + logger("Creating '$HPTEMP_RRD' file."); + eval { + RRDs::create($HPTEMP_RRD, + "--step=60", + "DS:hptemp1_1:GAUGE:120:0:100", + "DS:hptemp1_2:GAUGE:120:0:100", + "DS:hptemp1_3:GAUGE:120:0:100", + "DS:hptemp1_4:GAUGE:120:0:100", + "DS:hptemp1_5:GAUGE:120:0:100", + "DS:hptemp1_6:GAUGE:120:0:100", + "DS:hptemp1_7:GAUGE:120:0:100", + "DS:hptemp1_8:GAUGE:120:0:100", + "DS:hptemp2_1:GAUGE:120:0:100", + "DS:hptemp2_2:GAUGE:120:0:100", + "DS:hptemp2_3:GAUGE:120:0:100", + "DS:hptemp2_4:GAUGE:120:0:100", + "DS:hptemp2_5:GAUGE:120:0:100", + "DS:hptemp2_6:GAUGE:120:0:100", + "DS:hptemp3_1:GAUGE:120:0:100", + "DS:hptemp3_2:GAUGE:120:0:100", + "DS:hptemp3_3:GAUGE:120:0:100", + "DS:hptemp3_4:GAUGE:120:0:100", + "DS:hptemp3_5:GAUGE:120:0:100", + "DS:hptemp3_6:GAUGE:120:0:100", + "RRA:AVERAGE:0.5:1:1440", + "RRA:AVERAGE:0.5:30:336", + "RRA:AVERAGE:0.5:60:744", + "RRA:AVERAGE:0.5:1440:365", + "RRA:MIN:0.5:1:1440", + "RRA:MIN:0.5:30:336", + "RRA:MIN:0.5:60:744", + "RRA:MIN:0.5:1440:365", + "RRA:MAX:0.5:1:1440", + "RRA:MAX:0.5:30:336", + "RRA:MAX:0.5:60:744", + "RRA:MAX:0.5:1440:365", + "RRA:LAST:0.5:1:1440", + "RRA:LAST:0.5:30:336", + "RRA:LAST:0.5:60:744", + "RRA:LAST:0.5:1440:365", + ); + }; + my $err = RRDs::error; + if($@ || $err) { + logger("$@") unless !$@; + if($err) { + logger("ERROR: while creating $HPTEMP_RRD: $err"); + if($err eq "RRDs::error") { + logger("... is the RRDtool Perl package installed?"); + } + } + return; + } + } + + push(@graphs, "hptemp_update"); + if($opt_d eq "all" || $debug) { + logger("$myself: Ok"); + } +} + +sub hptemp_update { + my $myself = (caller(0))[3]; + my ($debug) = @_; + + my @hptemp1; + my @hptemp2; + my @hptemp3; + + my $l; + my $n; + my $rrdata = "N"; + + open(IN, "hplog -t |"); + my @data = ; + close(IN); + my $str; + for($l = 0; $l < scalar(@data); $l++) { + $_ = @data[$l]; + foreach my $t (@HPTEMP_1) { + $str = sprintf("%2d", $t); + if(/^$str /) { + my $temp = substr($_, 47, 3); + chomp($temp); + push(@hptemp1, int($temp)); + } + } + foreach my $t (@HPTEMP_2) { + $str = sprintf("%2d", $t); + if(/^$str /) { + my $temp = substr($_, 47, 3); + chomp($temp); + push(@hptemp2, int($temp)); + } + } + foreach my $t (@HPTEMP_3) { + $str = sprintf("%2d", $t); + if(/^$str /) { + my $temp = substr($_, 47, 3); + chomp($temp); + push(@hptemp3, int($temp)); + } + } + } + for($n = 0; $n < 8; $n++) { + $hptemp1[$n] = 0 unless $hptemp1[$n]; + $rrdata .= ":$hptemp1[$n]"; + } + for($n = 0; $n < 6; $n++) { + $hptemp2[$n] = 0 unless $hptemp2[$n]; + $rrdata .= ":$hptemp2[$n]"; + } + for($n = 0; $n < 6; $n++) { + $hptemp3[$n] = 0 unless $hptemp3[$n]; + $rrdata .= ":$hptemp3[$n]"; + } + + RRDs::update($HPTEMP_RRD, $rrdata); + if($opt_d eq "all" || $debug) { + logger("$myself: $rrdata"); + } + my $err = RRDs::error; + logger("ERROR: while updating $HPTEMP_RRD: $err") if $err; +} + +# LMSENS graph +# ---------------------------------------------------------------------------- +sub lmsens_init { + my $myself = (caller(0))[3]; + + if(!(-e $LMSENS_RRD)) { + logger("Creating '$LMSENS_RRD' file."); + eval { + RRDs::create($LMSENS_RRD, + "--step=60", + "DS:lmsens_mb0:GAUGE:120:0:100", + "DS:lmsens_mb1:GAUGE:120:0:100", + "DS:lmsens_cpu0:GAUGE:120:0:100", + "DS:lmsens_cpu1:GAUGE:120:0:100", + "DS:lmsens_cpu2:GAUGE:120:0:100", + "DS:lmsens_cpu3:GAUGE:120:0:100", + "DS:lmsens_fan0:GAUGE:120:0:U", + "DS:lmsens_fan1:GAUGE:120:0:U", + "DS:lmsens_fan2:GAUGE:120:0:U", + "DS:lmsens_fan3:GAUGE:120:0:U", + "DS:lmsens_fan4:GAUGE:120:0:U", + "DS:lmsens_fan5:GAUGE:120:0:U", + "DS:lmsens_fan6:GAUGE:120:0:U", + "DS:lmsens_fan7:GAUGE:120:0:U", + "DS:lmsens_fan8:GAUGE:120:0:U", + "DS:lmsens_core0:GAUGE:120:0:100", + "DS:lmsens_core1:GAUGE:120:0:100", + "DS:lmsens_core2:GAUGE:120:0:100", + "DS:lmsens_core3:GAUGE:120:0:100", + "DS:lmsens_core4:GAUGE:120:0:100", + "DS:lmsens_core5:GAUGE:120:0:100", + "DS:lmsens_core6:GAUGE:120:0:100", + "DS:lmsens_core7:GAUGE:120:0:100", + "DS:lmsens_core8:GAUGE:120:0:100", + "DS:lmsens_core9:GAUGE:120:0:100", + "DS:lmsens_core10:GAUGE:120:0:100", + "DS:lmsens_core11:GAUGE:120:0:100", + "DS:lmsens_core12:GAUGE:120:0:100", + "DS:lmsens_core13:GAUGE:120:0:100", + "DS:lmsens_core14:GAUGE:120:0:100", + "DS:lmsens_core15:GAUGE:120:0:100", + "DS:lmsens_volt0:GAUGE:120:U:U", + "DS:lmsens_volt1:GAUGE:120:U:U", + "DS:lmsens_volt2:GAUGE:120:U:U", + "DS:lmsens_volt3:GAUGE:120:U:U", + "DS:lmsens_volt4:GAUGE:120:U:U", + "DS:lmsens_volt5:GAUGE:120:U:U", + "DS:lmsens_volt6:GAUGE:120:U:U", + "DS:lmsens_volt7:GAUGE:120:U:U", + "DS:lmsens_volt8:GAUGE:120:U:U", + "DS:lmsens_volt9:GAUGE:120:U:U", + "DS:lmsens_volt10:GAUGE:120:U:U", + "DS:lmsens_volt11:GAUGE:120:U:U", + "DS:lmsens_gpu0:GAUGE:120:0:100", + "DS:lmsens_gpu1:GAUGE:120:0:100", + "DS:lmsens_gpu2:GAUGE:120:0:100", + "DS:lmsens_gpu3:GAUGE:120:0:100", + "DS:lmsens_gpu4:GAUGE:120:0:100", + "DS:lmsens_gpu5:GAUGE:120:0:100", + "DS:lmsens_gpu6:GAUGE:120:0:100", + "DS:lmsens_gpu7:GAUGE:120:0:100", + "DS:lmsens_gpu8:GAUGE:120:0:100", + "RRA:AVERAGE:0.5:1:1440", + "RRA:AVERAGE:0.5:30:336", + "RRA:AVERAGE:0.5:60:744", + "RRA:AVERAGE:0.5:1440:365", + "RRA:MIN:0.5:1:1440", + "RRA:MIN:0.5:30:336", + "RRA:MIN:0.5:60:744", + "RRA:MIN:0.5:1440:365", + "RRA:MAX:0.5:1:1440", + "RRA:MAX:0.5:30:336", + "RRA:MAX:0.5:60:744", + "RRA:MAX:0.5:1440:365", + "RRA:LAST:0.5:1:1440", + "RRA:LAST:0.5:30:336", + "RRA:LAST:0.5:60:744", + "RRA:LAST:0.5:1440:365", + ); + }; + my $err = RRDs::error; + if($@ || $err) { + logger("$@") unless !$@; + if($err) { + logger("ERROR: while creating $LMSENS_RRD: $err"); + if($err eq "RRDs::error") { + logger("... is the RRDtool Perl package installed?"); + } + } + return; + } + } + + push(@graphs, "lmsens_update"); + if($opt_d eq "all" || $debug) { + logger("$myself: Ok"); + } +} + +sub get_nvidia_data { + my ($gpu) = @_; + my $total = 0; + my $used = 0; + my $mem = 0; + my $cpu = 0; + my $temp = 0; + my $check_mem = 0; + my $check_cpu = 0; + my $check_temp = 0; + + open(IN, "nvidia-smi -q -i $gpu -d MEMORY,UTILIZATION,TEMPERATURE |"); + my @data = ; + close(IN); + for($l = 0; $l < scalar(@data); $l++) { + $_ = @data[$l]; + if(/Memory Usage/) { + $check_mem = 1; + next; + } + if($check_mem) { + if(/Total/) { + my (undef, $tmp) = split(':', $_); + if($tmp eq "\n") { + $l++; + $tmp = $data[$l]; + } + my ($value, undef) = split(' ', $tmp); + $value =~ s/[-]/./; + $value =~ s/[^0-9.]//g; + if(int($value) > 0) { + $total = int($value); + } + } + if(/Used/) { + my (undef, $tmp) = split(':', $_); + if($tmp eq "\n") { + $l++; + $tmp = $data[$l]; + } + my ($value, undef) = split(' ', $tmp); + $value =~ s/[-]/./; + $value =~ s/[^0-9.]//g; + if(int($value) > 0) { + $used = int($value); + } + $check_mem = 0; + } + } + + if(/Utilization/) { + $check_cpu = 1; + next; + } + if($check_cpu) { + if(/Gpu/) { + my (undef, $tmp) = split(':', $_); + if($tmp eq "\n") { + $l++; + $tmp = $data[$l]; + } + my ($value, undef) = split(' ', $tmp); + $value =~ s/[-]/./; + $value =~ s/[^0-9.]//g; + if(int($value) > 0) { + $cpu = int($value); + } + } + if(/Memory/) { + my (undef, $tmp) = split(':', $_); + if($tmp eq "\n") { + $l++; + $tmp = $data[$l]; + } + my ($value, undef) = split(' ', $tmp); + $value =~ s/[-]/./; + $value =~ s/[^0-9.]//g; + if(int($value) > 0) { + $mem = int($value); + } + } + $check_cpu = 0; + } + + if(/Temperature/) { + $check_temp = 1; + next; + } + if($check_temp) { + if(/Gpu/) { + my (undef, $tmp) = split(':', $_); + if($tmp eq "\n") { + $l++; + $tmp = $data[$l]; + } + my ($value, undef) = split(' ', $tmp); + $value =~ s/[-]/./; + $value =~ s/[^0-9.]//g; + if(int($value) > 0) { + $temp = int($value); + } + } + $check_temp = 0; + } + } + # NVIDIA driver v285.+ not supported (needs new output parsing). + # This is to avoid a divide by zero message. + if($total) { + $mem = ($used * 100) / $total; + } else { + $mem = $used = $total = 0; + } + return join(" ", $mem, $cpu, $temp); +} + +sub lmsens_update { + my $myself = (caller(0))[3]; + my ($debug) = @_; + + my @mb; + my @cpu; + my @fan; + my @core; + my @volt; + my @gpu; + + my $l; + my $n; + my $rrdata = "N"; + + if($os eq "Linux") { + if(scalar(%SENSORS_LIST)) { + open(IN, "sensors |"); + my @data = ; + close(IN); + my $str; + for($l = 0; $l < scalar(@data); $l++) { + $_ = @data[$l]; + for($n = 0; $n < 2; $n++) { + $str = "MB" . $n; + $mb[$n] = 0 unless $mb[$n]; + if($SENSORS_LIST{$str} && (/^$SENSORS_LIST{$str}:/) && (!/RPM/)) { + my (undef, $tmp) = split(':', $_); + if($tmp eq "\n") { + $l++; + $tmp = $data[$l]; + } + my ($value, undef) = split(' ', $tmp); + $mb[$n] = int($value); + } + } + for($n = 0; $n < 4; $n++) { + $str = "CPU" . $n; + $cpu[$n] = 0 unless $cpu[$n]; + if($SENSORS_LIST{$str} && (/^$SENSORS_LIST{$str}:/) && (!/RPM/)) { + my (undef, $tmp) = split(':', $_); + if($tmp eq "\n") { + $l++; + $tmp = $data[$l]; + } + my ($value, undef) = split(' ', $tmp); + $cpu[$n] = int($value); + } + } + for($n = 0; $n < 9; $n++) { + $str = "FAN" . $n; + $fan[$n] = 0 unless $fan[$n]; + if($SENSORS_LIST{$str} && (/^$SENSORS_LIST{$str}:/) && (/RPM/)) { + my (undef, $tmp) = split(':', $_); + if($tmp eq "\n") { + $l++; + $tmp = $data[$l]; + } + my ($value, undef) = split(' ', $tmp); + $fan[$n] = int($value); + } + } + for($n = 0; $n < 16; $n++) { + $str = "CORE" . $n; + $core[$n] = 0 unless $core[$n]; + if($SENSORS_LIST{$str} && (/^$SENSORS_LIST{$str}:/) && (!/RPM/)) { + my (undef, $tmp) = split(':', $_); + if($tmp eq "\n") { + $l++; + $tmp = $data[$l]; + } + my ($value, undef) = split(' ', $tmp); + $core[$n] = int($value); + } + } + for($n = 0; $n < 12; $n++) { + $str = "VOLT" . $n; + $volt[$n] = 0 unless $volt[$n]; + if($SENSORS_LIST{$str} && (/^$SENSORS_LIST{$str}:/) && (!/RPM/)) { + my (undef, $tmp) = split(':', $_); + if($tmp eq "\n") { + $l++; + $tmp = $data[$l]; + } + my ($value, undef) = split(' ', $tmp); + $volt[$n] = $value; + } + } + } + for($n = 0; $n < 9; $n++) { + $str = "GPU" . $n; + $gpu[$n] = 0 unless $gpu[$n]; + if($SENSORS_LIST{$str} && $SENSORS_LIST{$str} eq "nvidia") { + (undef, undef, $gpu[$n]) = split(' ', get_nvidia_data($n)); + if(!$gpu[$n]) { + # attempt to get data using the old driver version + open(IN, "nvidia-smi -g $n |"); + my @data = ; + close(IN); + for($l = 0; $l < scalar(@data); $l++) { + $_ = @data[$l]; + if(/Temperature/) { + my (undef, $tmp) = split(':', $_); + if($tmp eq "\n") { + $l++; + $tmp = $data[$l]; + } + my ($value, undef) = split(' ', $tmp); + $value =~ s/[-]/./; + $value =~ s/[^0-9.]//g; + if(int($value) > 0) { + $gpu[$n] = int($value); + } + } + } + } + } + } + } + for($n = 0; $n < scalar(@mb); $n++) { + $rrdata .= ":$mb[$n]"; + } + for($n = 0; $n < scalar(@cpu); $n++) { + $rrdata .= ":$cpu[$n]"; + } + for($n = 0; $n < scalar(@fan); $n++) { + $rrdata .= ":$fan[$n]"; + } + for($n = 0; $n < scalar(@core); $n++) { + $rrdata .= ":$core[$n]"; + } + for($n = 0; $n < scalar(@volt); $n++) { + $rrdata .= ":$volt[$n]"; + } + for($n = 0; $n < scalar(@gpu); $n++) { + $rrdata .= ":$gpu[$n]"; + } + } + + RRDs::update($LMSENS_RRD, $rrdata); + if($opt_d eq "all" || $debug) { + logger("$myself: $rrdata"); + } + my $err = RRDs::error; + logger("ERROR: while updating $LMSENS_RRD: $err") if $err; +} + +# NVIDIA graph +# ---------------------------------------------------------------------------- +sub nvidia_init { + my $myself = (caller(0))[3]; + + if(!(-e $NVIDIA_RRD)) { + logger("Creating '$NVIDIA_RRD' file."); + eval { + RRDs::create($NVIDIA_RRD, + "--step=60", + "DS:nvidia_temp0:GAUGE:120:0:U", + "DS:nvidia_temp1:GAUGE:120:0:U", + "DS:nvidia_temp2:GAUGE:120:0:U", + "DS:nvidia_temp3:GAUGE:120:0:U", + "DS:nvidia_temp4:GAUGE:120:0:U", + "DS:nvidia_temp5:GAUGE:120:0:U", + "DS:nvidia_temp6:GAUGE:120:0:U", + "DS:nvidia_temp7:GAUGE:120:0:U", + "DS:nvidia_temp8:GAUGE:120:0:U", + "DS:nvidia_gpu0:GAUGE:120:0:100", + "DS:nvidia_gpu1:GAUGE:120:0:100", + "DS:nvidia_gpu2:GAUGE:120:0:100", + "DS:nvidia_gpu3:GAUGE:120:0:100", + "DS:nvidia_gpu4:GAUGE:120:0:100", + "DS:nvidia_gpu5:GAUGE:120:0:100", + "DS:nvidia_gpu6:GAUGE:120:0:100", + "DS:nvidia_gpu7:GAUGE:120:0:100", + "DS:nvidia_gpu8:GAUGE:120:0:100", + "DS:nvidia_mem0:GAUGE:120:0:100", + "DS:nvidia_mem1:GAUGE:120:0:100", + "DS:nvidia_mem2:GAUGE:120:0:100", + "DS:nvidia_mem3:GAUGE:120:0:100", + "DS:nvidia_mem4:GAUGE:120:0:100", + "DS:nvidia_mem5:GAUGE:120:0:100", + "DS:nvidia_mem6:GAUGE:120:0:100", + "DS:nvidia_mem7:GAUGE:120:0:100", + "DS:nvidia_mem8:GAUGE:120:0:100", + "RRA:AVERAGE:0.5:1:1440", + "RRA:AVERAGE:0.5:30:336", + "RRA:AVERAGE:0.5:60:744", + "RRA:AVERAGE:0.5:1440:365", + "RRA:MIN:0.5:1:1440", + "RRA:MIN:0.5:30:336", + "RRA:MIN:0.5:60:744", + "RRA:MIN:0.5:1440:365", + "RRA:MAX:0.5:1:1440", + "RRA:MAX:0.5:30:336", + "RRA:MAX:0.5:60:744", + "RRA:MAX:0.5:1440:365", + "RRA:LAST:0.5:1:1440", + "RRA:LAST:0.5:30:336", + "RRA:LAST:0.5:60:744", + "RRA:LAST:0.5:1440:365", + ); + }; + my $err = RRDs::error; + if($@ || $err) { + logger("$@") unless !$@; + if($err) { + logger("ERROR: while creating $NVIDIA_RRD: $err"); + if($err eq "RRDs::error") { + logger("... is the RRDtool Perl package installed?"); + } + } + return; + } + } + + push(@graphs, "nvidia_update"); + if($opt_d eq "all" || $debug) { + logger("$myself: Ok"); + } +} + +sub nvidia_update { + my $myself = (caller(0))[3]; + my ($debug) = @_; + + my @temp; + my @gpu; + my @mem; + my @data; + my $utilization; + + my $l; + my $n; + my $rrdata = "N"; + + for($n = 0; $n < 9; $n++) { + $temp[$n] = 0; + $gpu[$n] = 0; + $mem[$n] = 0; + if($n < $NVIDIA_MAX) { + ($mem[$n], $gpu[$n], $temp[$n]) = split(' ', get_nvidia_data($n)); + if(!$temp[$n] && !$gpu[$n] && !$mem[$n]) { + # attempt to get data using the old driver version + $utilization = 0; + open(IN, "nvidia-smi -g $n |"); + @data = ; + close(IN); + for($l = 0; $l < scalar(@data); $l++) { + $_ = @data[$l]; + if(/Temperature/) { + my (undef, $tmp) = split(':', $_); + if($tmp eq "\n") { + $l++; + $tmp = $data[$l]; + } + my ($value, undef) = split(' ', $tmp); + $value =~ s/[-]/./; + $value =~ s/[^0-9.]//g; + if(int($value) > 0) { + $temp[$n] = int($value); + } + } + if(/Utilization/) { + $utilization = 1; + } + if($utilization == 1) { + if(/GPU/) { + my (undef, $tmp) = split(':', $_); + if($tmp eq "\n") { + $l++; + $tmp = $data[$l]; + } + my ($value, undef) = split(' ', $tmp); + $value =~ s/[-]/./; + $value =~ s/[^0-9.]//g; + if(int($value) > 0) { + $gpu[$n] = int($value); + } + } + if(/Memory/) { + my (undef, $tmp) = split(':', $_); + if($tmp eq "\n") { + $l++; + $tmp = $data[$l]; + } + my ($value, undef) = split(' ', $tmp); + $value =~ s/[-]/./; + $value =~ s/[^0-9.]//g; + if(int($value) > 0) { + $mem[$n] = int($value); + } + } + } + } + } + } + } + + for($n = 0; $n < scalar(@temp); $n++) { + $rrdata .= ":$temp[$n]"; + } + for($n = 0; $n < scalar(@gpu); $n++) { + $rrdata .= ":$gpu[$n]"; + } + for($n = 0; $n < scalar(@mem); $n++) { + $rrdata .= ":$mem[$n]"; + } + + RRDs::update($NVIDIA_RRD, $rrdata); + if($opt_d eq "all" || $debug) { + logger("$myself: $rrdata"); + } + my $err = RRDs::error; + logger("ERROR: while updating $NVIDIA_RRD: $err") if $err; +} + +# DISK graph +# ---------------------------------------------------------------------------- +sub disk_init { + my $myself = (caller(0))[3]; + + my $info; + my @ds; + my @tmp; + my $n; + + # This warns and transforms an old @DISK_LIST array (before 2.6) into + # the new two-dimensional array to keep backwards compatibility. + my @tmp2; + if(!(ref($DISK_LIST[0]) eq "ARRAY")) { + logger("$myself: \@DISK_LIST array format is outdated. Please check monitorix.conf(5) man page to see how this array must be defined."); + push(@{$tmp2[0]}, @DISK_LIST); + @DISK_LIST = @tmp2; + } + + if(-e $DISK_RRD) { + $info = RRDs::info($DISK_RRD); + for my $key (keys %$info) { + if(index($key, 'ds[') == 0) { + if(index($key, '.type') != -1) { + push(@ds, substr($key, 3, index($key, ']') - 3)); + } + } + } + if(scalar(@ds) / 24 != scalar(@DISK_LIST)) { + logger("Detected size mismatch between \@DISK_LIST (" . scalar(@DISK_LIST) . ") and $DISK_RRD (" . scalar(@ds) / 24 . "). Resizing it accordingly. All historic data will be lost. Backup file created."); + rename($DISK_RRD, "$DISK_RRD.bak"); + } + } + + if(!(-e $DISK_RRD)) { + logger("Creating '$DISK_RRD' file."); + for($n = 0; $n < scalar(@DISK_LIST); $n++) { + push(@tmp, "DS:disk" . $n . "_hd0_temp:GAUGE:120:0:100"); + push(@tmp, "DS:disk" . $n . "_hd0_smart1:GAUGE:120:0:U"); + push(@tmp, "DS:disk" . $n . "_hd0_smart2:GAUGE:120:0:U"); + push(@tmp, "DS:disk" . $n . "_hd1_temp:GAUGE:120:0:100"); + push(@tmp, "DS:disk" . $n . "_hd1_smart1:GAUGE:120:0:U"); + push(@tmp, "DS:disk" . $n . "_hd1_smart2:GAUGE:120:0:U"); + push(@tmp, "DS:disk" . $n . "_hd2_temp:GAUGE:120:0:100"); + push(@tmp, "DS:disk" . $n . "_hd2_smart1:GAUGE:120:0:U"); + push(@tmp, "DS:disk" . $n . "_hd2_smart2:GAUGE:120:0:U"); + push(@tmp, "DS:disk" . $n . "_hd3_temp:GAUGE:120:0:100"); + push(@tmp, "DS:disk" . $n . "_hd3_smart1:GAUGE:120:0:U"); + push(@tmp, "DS:disk" . $n . "_hd3_smart2:GAUGE:120:0:U"); + push(@tmp, "DS:disk" . $n . "_hd4_temp:GAUGE:120:0:100"); + push(@tmp, "DS:disk" . $n . "_hd4_smart1:GAUGE:120:0:U"); + push(@tmp, "DS:disk" . $n . "_hd4_smart2:GAUGE:120:0:U"); + push(@tmp, "DS:disk" . $n . "_hd5_temp:GAUGE:120:0:100"); + push(@tmp, "DS:disk" . $n . "_hd5_smart1:GAUGE:120:0:U"); + push(@tmp, "DS:disk" . $n . "_hd5_smart2:GAUGE:120:0:U"); + push(@tmp, "DS:disk" . $n . "_hd6_temp:GAUGE:120:0:100"); + push(@tmp, "DS:disk" . $n . "_hd6_smart1:GAUGE:120:0:U"); + push(@tmp, "DS:disk" . $n . "_hd6_smart2:GAUGE:120:0:U"); + push(@tmp, "DS:disk" . $n . "_hd7_temp:GAUGE:120:0:100"); + push(@tmp, "DS:disk" . $n . "_hd7_smart1:GAUGE:120:0:U"); + push(@tmp, "DS:disk" . $n . "_hd7_smart2:GAUGE:120:0:U"); + } + eval { + RRDs::create($DISK_RRD, + "--step=60", + @tmp, + "RRA:AVERAGE:0.5:1:1440", + "RRA:AVERAGE:0.5:30:336", + "RRA:AVERAGE:0.5:60:744", + "RRA:AVERAGE:0.5:1440:365", + "RRA:MIN:0.5:1:1440", + "RRA:MIN:0.5:30:336", + "RRA:MIN:0.5:60:744", + "RRA:MIN:0.5:1440:365", + "RRA:MAX:0.5:1:1440", + "RRA:MAX:0.5:30:336", + "RRA:MAX:0.5:60:744", + "RRA:MAX:0.5:1440:365", + "RRA:LAST:0.5:1:1440", + "RRA:LAST:0.5:30:336", + "RRA:LAST:0.5:60:744", + "RRA:LAST:0.5:1440:365", + ); + }; + my $err = RRDs::error; + if($@ || $err) { + logger("$@") unless !$@; + if($err) { + logger("ERROR: while creating $DISK_RRD: $err"); + if($err eq "RRDs::error") { + logger("... is the RRDtool Perl package installed?"); + } + } + return; + } + } + + # Since 2.6.0 disk.rrd supports unlimited disk device monitoring, this + # forces to rename the DS of the first disk accordingly. + for($n = 0; $n < 8; $n++) { + RRDs::tune($DISK_RRD, + "--data-source-rename=disk_hd" . $n . "_temp:disk0_hd" . $n . "_temp", + "--data-source-rename=disk_hd" . $n . "_smart1:disk0_hd" . $n . "_smart1", + "--data-source-rename=disk_hd" . $n . "_smart2:disk0_hd" . $n . "_smart2", + ); + } + + push(@graphs, "disk_update"); + if($opt_d eq "all" || $debug) { + logger("$myself: Ok"); + } +} + +sub disk_update { + my $myself = (caller(0))[3]; + my ($debug) = @_; + + my $temp; + my $smart1; + my $smart2; + + my $n; + my $rrdata = "N"; + + foreach my $i (@DISK_LIST) { + for($n = 0; $n < 8; $n++) { + $temp = 0; + $smart1 = 0; + $smart2 = 0; + if(@$i[$n]) { + my $d = @$i[$n]; + open(IN, "smartctl -A $d |"); + while() { + if(/^ 5/ && /Reallocated_Sector_Ct/) { + my @tmp = split(' ', $_); + $smart1 = $tmp[9]; + chomp($smart1); + } + if(/^194/ && /Temperature_Celsius/) { + my @tmp = split(' ', $_); + $temp = $tmp[9]; + chomp($temp); + } + if(/^197/ && /Current_Pending_Sector/) { + my @tmp = split(' ', $_); + $smart2 = $tmp[9]; + chomp($smart2); + } + if(/^Current Drive Temperature: /) { + my @tmp = split(' ', $_); + $temp = $tmp[3] unless $temp; + chomp($temp); + } + } + close(IN); + $temp = `hddtemp -wqn $d` unless $temp; + chomp($temp); + } + $rrdata .= ":$temp"; + $rrdata .= ":$smart1"; + $rrdata .= ":$smart2"; + } + } + + RRDs::update($DISK_RRD, $rrdata); + if($opt_d eq "all" || $debug) { + logger("$myself: $rrdata"); + } + my $err = RRDs::error; + logger("ERROR: while updating $DISK_RRD: $err") if $err; +} + +# FS graph +# ---------------------------------------------------------------------------- +sub is_in_diskstats { + my ($d, $major, $minor) = @_; + + open(IN, "/proc/diskstats"); + my @data = ; + close(IN); + foreach(@data) { + my ($maj, $min, $device) = split(' ', $_); + return $device unless $d ne $device; + if($maj == $major && $min == $minor) { + return $device; + } + } +} + +sub is_luks { + my ($d) = @_; + + if($d =~ m/luks/) { + $d =~ s/luks-//; + $d = `blkid -t UUID=$d | awk -F ":" '{ print \$1 }'`; + chomp($d); + $d =~ s/^.*dev\///; # remove the /dev/ prefix + $d =~ s/^.*mapper\///; # remove the mapper/ prefix + return $d; + } +} + +sub fs_init { + my $myself = (caller(0))[3]; + our %FS_DEV; + + my $info; + my @ds; + my @tmp; + my $n; + + # This warns if an old @FS_LIST array (before 2.6) is still used. + my @tmp2; + if(!(ref($FS_LIST[0]) eq "ARRAY")) { + logger("$myself: \@FS_LIST array format is outdated. Please check monitorix.conf(5) man page to see how this array must be defined."); + push(@{$tmp2[0]}, @FS_LIST); + @FS_LIST = @tmp2; + } + + if(-e $FS_RRD) { + $info = RRDs::info($FS_RRD); + for my $key (keys %$info) { + if(index($key, 'ds[') == 0) { + if(index($key, '.type') != -1) { + push(@ds, substr($key, 3, index($key, ']') - 3)); + } + } + } + if(scalar(@ds) / 24 != scalar(@FS_LIST)) { + logger("Detected size mismatch between \@FS_LIST (" . scalar(@FS_LIST) . ") and $FS_RRD (" . scalar(@ds) / 24 . "). Resizing it accordingly. All historic data will be lost. Backup file created."); + rename($FS_RRD, "$FS_RRD.bak"); + } + } + + if(!(-e $FS_RRD)) { + logger("Creating '$FS_RRD' file."); + for($n = 0; $n < scalar(@FS_LIST); $n++) { + push(@tmp, "DS:fs" . $n . "_use0:GAUGE:120:0:100"); + push(@tmp, "DS:fs" . $n . "_ioa0:GAUGE:120:0:U"); + push(@tmp, "DS:fs" . $n . "_tim0:GAUGE:120:0:U"); + push(@tmp, "DS:fs" . $n . "_use1:GAUGE:120:0:100"); + push(@tmp, "DS:fs" . $n . "_ioa1:GAUGE:120:0:U"); + push(@tmp, "DS:fs" . $n . "_tim1:GAUGE:120:0:U"); + push(@tmp, "DS:fs" . $n . "_use2:GAUGE:120:0:100"); + push(@tmp, "DS:fs" . $n . "_ioa2:GAUGE:120:0:U"); + push(@tmp, "DS:fs" . $n . "_tim2:GAUGE:120:0:U"); + push(@tmp, "DS:fs" . $n . "_use3:GAUGE:120:0:100"); + push(@tmp, "DS:fs" . $n . "_ioa3:GAUGE:120:0:U"); + push(@tmp, "DS:fs" . $n . "_tim3:GAUGE:120:0:U"); + push(@tmp, "DS:fs" . $n . "_use4:GAUGE:120:0:100"); + push(@tmp, "DS:fs" . $n . "_ioa4:GAUGE:120:0:U"); + push(@tmp, "DS:fs" . $n . "_tim4:GAUGE:120:0:U"); + push(@tmp, "DS:fs" . $n . "_use5:GAUGE:120:0:100"); + push(@tmp, "DS:fs" . $n . "_ioa5:GAUGE:120:0:U"); + push(@tmp, "DS:fs" . $n . "_tim5:GAUGE:120:0:U"); + push(@tmp, "DS:fs" . $n . "_use6:GAUGE:120:0:100"); + push(@tmp, "DS:fs" . $n . "_ioa6:GAUGE:120:0:U"); + push(@tmp, "DS:fs" . $n . "_tim6:GAUGE:120:0:U"); + push(@tmp, "DS:fs" . $n . "_use7:GAUGE:120:0:100"); + push(@tmp, "DS:fs" . $n . "_ioa7:GAUGE:120:0:U"); + push(@tmp, "DS:fs" . $n . "_tim7:GAUGE:120:0:U"); + } + eval { + RRDs::create($FS_RRD, + "--step=60", + @tmp, + "RRA:AVERAGE:0.5:1:1440", + "RRA:AVERAGE:0.5:30:336", + "RRA:AVERAGE:0.5:60:744", + "RRA:AVERAGE:0.5:1440:365", + "RRA:MIN:0.5:1:1440", + "RRA:MIN:0.5:30:336", + "RRA:MIN:0.5:60:744", + "RRA:MIN:0.5:1440:365", + "RRA:MAX:0.5:1:1440", + "RRA:MAX:0.5:30:336", + "RRA:MAX:0.5:60:744", + "RRA:MAX:0.5:1440:365", + "RRA:LAST:0.5:1:1440", + "RRA:LAST:0.5:30:336", + "RRA:LAST:0.5:60:744", + "RRA:LAST:0.5:1440:365", + ); + }; + my $err = RRDs::error; + if($@ || $err) { + logger("$@") unless !$@; + if($err) { + logger("ERROR: while creating $FS_RRD: $err"); + if($err eq "RRDs::error") { + logger("... is the RRDtool Perl package installed?"); + } + } + return; + } + } + + # This tries to find out the physical device name of each fs. + foreach my $i (@FS_LIST) { + foreach my $fs (@$i) { + my $d = $FS_DEV{$fs}; + + next unless !$d; + + if($fs ne "swap") { + eval { + alarm $TIMEOUT; + open(IN, "df -P $fs |"); + while() { + if(/ $fs$/) { + ($d) = split(' ', $_); + last; + } + } + close(IN); + alarm 0; + chomp($d); + }; + } + + if($os eq "Linux" && $kernel_branch > 2.4) { + my $lvm; + my $lvm_disk; + my $is_md; + my $found; + + if($fs eq "swap") { + $d = `cat /proc/swaps | tail -1 | awk -F " " '{ print \$1 }'`; + chomp($d); + } + + # check for device names using symbolic links + # e.g. /dev/disk/by-uuid/db312d12-0da6-44e5-a354-4c82118f4b66 + if(-l $d) { + $link = readlink($d); + $d = abs_path(dirname($d) . "/" . $link); + chomp($d); + } + + # get the major and minor of $d + my $rdev = (stat($d))[6]; + my $minor = $rdev % 256; + my $major = int($rdev / 256); + + # do exists in /proc/diskstats? + if($found = is_in_diskstats($d, $major, $minor)) { + $d = $found; + $FS_DEV{$fs} = $d; + logger("$myself: Detected physical device name for $fs in '$d'.") unless !$opt_d; + next; + } + + logger("$myself: Unable to find major/minor in /proc/diskstats.") unless !$opt_d; + + # check if device is using EVMS + if($d =~ m/\/dev\/evms\//) { + $d = `evms_query disks $d`; + if($found = is_in_diskstats($d)) { + $d = $found; + $FS_DEV{$fs} = $d; + logger("$myself: Detected physical device name for $fs in '$d'.") unless !$opt_d; + next; + } + } + + $d =~ s/^.*dev\///; # remove the /dev/ prefix + $d =~ s/^.*mapper\///; # remove the mapper/ prefix + + # check if the device is under a crypt LUKS (encrypted fs) + if($dev = is_luks($d)) { + $d = $dev; + } + + # do exists in /proc/diskstats? + if($found = is_in_diskstats($d)) { + $d = $found; + $FS_DEV{$fs} = $d; + logger("$myself: Detected physical device name for $fs in '$d'.") unless !$opt_d; + next; + } + + # check if the device is in a LVM + $lvm = $d; + $lvm =~ s/-.*//; + if($lvm ne $d) { # probably LVM + if(system("pvs >/dev/null 2>&1") == 0 && $lvm) { + $lvm_disk = `pvs --noheadings | grep $lvm | tail -1 | awk -F " " '{ print \$1 }'`; + chomp($lvm_disk); + $lvm_disk =~ s/^.*dev\///; # remove the /dev/ prefix + $lvm_disk =~ s/^.*mapper\///; # remove the mapper/ prefix + if(!($lvm_disk =~ m/md/)) { + if($lvm_disk =~ m/cciss/) { + # LVM over a CCISS disk (/dev/cciss/c0d0) + $d = $lvm_disk; + chomp($d); + } elsif($dev = is_luks($lvm_disk)) { + $d = $dev; + } else { + # LVM over a direct disk (/dev/sda1) + $d = $lvm_disk; + chomp($d); + } + } else { + # LVM over Linux RAID combination (/dev/md1) + $d = $lvm_disk; + chomp($d); + } + } + } + } elsif($os eq "FreeBSD" || $os eq "OpenBSD" || $os eq "NetBSD") { + # remove the /dev/ prefix + if ($d =~ s/^.*dev\///) { + # not ZFS; get the device name, eg ada0; md0; ad10 + $d =~ s/^(\D+\d*)\D.*/\1/; + } else { + # Just take ZFS pool name + $d =~ s,^([^/]*)/.*,\1,; + } + } + $FS_DEV{$fs} = $d; + logger("$myself: Detected physical device name for $fs in '$d'.") unless !$opt_d; + } + } + + our %fs_hist = (); + push(@graphs, "fs_update"); + if($opt_d eq "all" || $debug) { + logger("$myself: Ok"); + } +} + +sub fs_update { + my $myself = (caller(0))[3]; + my ($debug) = @_; + + my @tmp; + my $val; + my $str; + my $n; + my $rrdata = "N"; + + my $e = 0; + foreach my $i (@FS_LIST) { + for($n = 0; $n < 8; $n++) { + my $use = 0; + my $ioa = 0; + my $tim = 0; + + my $used = 0; + my $free = 0; + + $fs = @$i[$n]; + if($fs eq "swap") { + if($os eq "Linux") { + open(IN, "free |"); + while() { + if(/^Swap:\s+\d+\s+(\d+)\s+(\d+)$/) { + $used = $1; + $free = $2; + } + } + close(IN); + } elsif($os eq "FreeBSD") { + open(IN, "swapinfo -k |"); + while() { + if(/^.*?\s+\d+\s+(\d+)\s+(\d+)\s+\d+\%$/) { + $used = $1; + $free = $2; + } + } + close(IN); + } elsif($os eq "OpenBSD" || $os eq "NetBSD") { + open(IN, "pstat -sk |"); + while() { + if(/^swap_device\s+\d+\s+(\d+)\s+(\d+) /) { + $used = $1; + $free = $2; + } + } + close(IN); + } + + chomp($used, $free); + # prevents a division by 0 if swap device is not used + $use = ($used * 100) / ($used + $free) unless $used + $free == 0; + } elsif($fs) { + eval { + alarm $TIMEOUT; + open(IN, "df -P $fs |"); + while() { + if(/ $fs$/) { + @tmp = split(' ', $_); + last; + } + } + close(IN); + alarm 0; + }; + (undef, undef, $used, $free) = @tmp; + chomp($used, $free); + $use = ($used * 100) / ($used + $free); + + # FS alert + if($fs eq "/" && $ENABLE_ALERTS eq "Y") { + if(!$ALERT_ROOTFS_THRESHOLD || $pcnt < $ALERT_ROOTFS_THRESHOLD) { + $fs_hist{'rootalert'} = 0; + } else { + if(!$fs_hist{'rootalert'}) { + $fs_hist{'rootalert'} = time; + } + if($fs_hist{'rootalert'} > 0 && (time - $fs_hist{'rootalert'}) > $ALERT_ROOTFS_TIMEINTVL) { + if(-x $ALERT_ROOTFS_SCRIPT) { + system($ALERT_ROOTFS_SCRIPT . " " . $ALERT_ROOTFS_TIMEINTVL . " " . $ALERT_ROOTFS_THRESHOLD . " " . $pcnt); + } + $fs_hist{'rootalert'} = time; + } + } + } + } + + my $read_cnt = 0; + my $read_sec = 0; + my $write_cnt = 0; + my $write_sec = 0; + my $d = $FS_DEV{$fs}; + if($d) { + if($os eq "Linux") { + if($kernel_branch > 2.4) { + open(IN, "/proc/diskstats"); + while() { + if(/ $d /) { + @tmp = split(' ', $_); + last; + } + } + close(IN); + (undef, undef, undef, $read_cnt, undef, undef, $read_sec, $write_cnt, undef, undef, $write_sec) = @tmp; + } else { + my $io; + open(IN, "/proc/stat"); + while() { + if(/^disk_io/) { + (undef, undef, $io) = split(':', $_); + last; + } + } + close(IN); + (undef, $read_cnt, $read_sec, $write_cnt, $write_sec) = split(',', $io); + $write_sec =~ s/\).*$//; + } + } elsif($os eq "FreeBSD") { + @tmp = split(' ', `iostat -xI $d | grep -w $d`); + if(@tmp) { + (undef, $read_cnt, $write_cnt, $read_sec, $write_sec) = @tmp; + $read_cnt = int($read_cnt); + $write_cnt = int($write_cnt); + $read_sec = int($read_sec); + $write_sec = int($write_sec); + } else { + @tmp = split(' ', `iostat -dI | tail -1`); + (undef, $read_cnt, $read_sec) = @tmp; + $write_cnt = ""; + $write_sec = ""; + chomp($read_sec); + $read_sec = int($read_sec); + } + } elsif($os eq "OpenBSD" || $os eq "NetBSD") { + @tmp = split(' ', `iostat -DI | tail -1`); + ($read_cnt, $read_sec) = @tmp; + $write_cnt = ""; + $write_sec = ""; + chomp($read_sec); + $read_sec = int($read_sec); + } + } + + $ioa = $read_cnt + $write_cnt; + $tim = $read_sec + $write_sec; + + $str = $e . "_ioa" . $n; + $val = $ioa; + $ioa = $val - $fs_hist{$str}; + $ioa = 0 unless $val != $ioa; + $ioa /= 60; + $fs_hist{$str} = $val; + + $str = $e . "_tim" . $n; + $val = $tim; + $tim = $val - $fs_hist{$str}; + $tim = 0 unless $val != $tim; + $tim /= 60; + $fs_hist{$str} = $val; + + $rrdata .= ":$use:$ioa:$tim"; + } + $e++; + } + + RRDs::update($FS_RRD, $rrdata); + if($opt_d eq "all" || $debug) { + logger("$myself: $rrdata"); + } + my $err = RRDs::error; + logger("ERROR: while updating $FS_RRD: $err") if $err; +} + +# NET graph +# ---------------------------------------------------------------------------- +sub net_init { + my $myself = (caller(0))[3]; + + if(!(-e $NET_RRD)) { + logger("Creating '$NET_RRD' file."); + eval { + RRDs::create($NET_RRD, + "--step=60", + "DS:net0_bytes_in:COUNTER:120:0:U", + "DS:net0_bytes_out:COUNTER:120:0:U", + "DS:net0_packs_in:COUNTER:120:0:U", + "DS:net0_packs_out:COUNTER:120:0:U", + "DS:net0_error_in:COUNTER:120:0:U", + "DS:net0_error_out:COUNTER:120:0:U", + "DS:net1_bytes_in:COUNTER:120:0:U", + "DS:net1_bytes_out:COUNTER:120:0:U", + "DS:net1_packs_in:COUNTER:120:0:U", + "DS:net1_packs_out:COUNTER:120:0:U", + "DS:net1_error_in:COUNTER:120:0:U", + "DS:net1_error_out:COUNTER:120:0:U", + "DS:net2_bytes_in:COUNTER:120:0:U", + "DS:net2_bytes_out:COUNTER:120:0:U", + "DS:net2_packs_in:COUNTER:120:0:U", + "DS:net2_packs_out:COUNTER:120:0:U", + "DS:net2_error_in:COUNTER:120:0:U", + "DS:net2_error_out:COUNTER:120:0:U", + "DS:net3_bytes_in:COUNTER:120:0:U", + "DS:net3_bytes_out:COUNTER:120:0:U", + "DS:net3_packs_in:COUNTER:120:0:U", + "DS:net3_packs_out:COUNTER:120:0:U", + "DS:net3_error_in:COUNTER:120:0:U", + "DS:net3_error_out:COUNTER:120:0:U", + "DS:net4_bytes_in:COUNTER:120:0:U", + "DS:net4_bytes_out:COUNTER:120:0:U", + "DS:net4_packs_in:COUNTER:120:0:U", + "DS:net4_packs_out:COUNTER:120:0:U", + "DS:net4_error_in:COUNTER:120:0:U", + "DS:net4_error_out:COUNTER:120:0:U", + "DS:net5_bytes_in:COUNTER:120:0:U", + "DS:net5_bytes_out:COUNTER:120:0:U", + "DS:net5_packs_in:COUNTER:120:0:U", + "DS:net5_packs_out:COUNTER:120:0:U", + "DS:net5_error_in:COUNTER:120:0:U", + "DS:net5_error_out:COUNTER:120:0:U", + "DS:net6_bytes_in:COUNTER:120:0:U", + "DS:net6_bytes_out:COUNTER:120:0:U", + "DS:net6_packs_in:COUNTER:120:0:U", + "DS:net6_packs_out:COUNTER:120:0:U", + "DS:net6_error_in:COUNTER:120:0:U", + "DS:net6_error_out:COUNTER:120:0:U", + "DS:net7_bytes_in:COUNTER:120:0:U", + "DS:net7_bytes_out:COUNTER:120:0:U", + "DS:net7_packs_in:COUNTER:120:0:U", + "DS:net7_packs_out:COUNTER:120:0:U", + "DS:net7_error_in:COUNTER:120:0:U", + "DS:net7_error_out:COUNTER:120:0:U", + "DS:net8_bytes_in:COUNTER:120:0:U", + "DS:net8_bytes_out:COUNTER:120:0:U", + "DS:net8_packs_in:COUNTER:120:0:U", + "DS:net8_packs_out:COUNTER:120:0:U", + "DS:net8_error_in:COUNTER:120:0:U", + "DS:net8_error_out:COUNTER:120:0:U", + "DS:net9_bytes_in:COUNTER:120:0:U", + "DS:net9_bytes_out:COUNTER:120:0:U", + "DS:net9_packs_in:COUNTER:120:0:U", + "DS:net9_packs_out:COUNTER:120:0:U", + "DS:net9_error_in:COUNTER:120:0:U", + "DS:net9_error_out:COUNTER:120:0:U", + "RRA:AVERAGE:0.5:1:1440", + "RRA:AVERAGE:0.5:30:336", + "RRA:AVERAGE:0.5:60:744", + "RRA:AVERAGE:0.5:1440:365", + "RRA:MIN:0.5:1:1440", + "RRA:MIN:0.5:30:336", + "RRA:MIN:0.5:60:744", + "RRA:MIN:0.5:1440:365", + "RRA:MAX:0.5:1:1440", + "RRA:MAX:0.5:30:336", + "RRA:MAX:0.5:60:744", + "RRA:MAX:0.5:1440:365", + "RRA:LAST:0.5:1:1440", + "RRA:LAST:0.5:30:336", + "RRA:LAST:0.5:60:744", + "RRA:LAST:0.5:1440:365", + ); + }; + my $err = RRDs::error; + if($@ || $err) { + logger("$@") unless !$@; + if($err) { + logger("ERROR: while creating $NET_RRD: $err"); + if($err eq "RRDs::error") { + logger("... is the RRDtool Perl package installed?"); + } + } + return; + } + } + + push(@graphs, "net_update"); + if($opt_d eq "all" || $debug) { + logger("$myself: Ok"); + } +} + +sub net_update { + my $myself = (caller(0))[3]; + my ($debug) = @_; + + my @net_bytes_in; + my @net_bytes_out; + my @net_packs_in; + my @net_packs_out; + my @net_error_in; + my @net_error_out; + + my $n; + my $rrdata = "N"; + + for($n = 0; $n < 10 ; $n++) { + $net_bytes_in[$n] = 0; + $net_bytes_out[$n] = 0; + $net_packs_in[$n] = 0; + $net_packs_out[$n] = 0; + $net_error_in[$n] = 0; + $net_error_out[$n] = 0; + if($n < scalar(@NET_LIST)) { + if($os eq "Linux") { + open(IN, "/proc/net/dev"); + my $dev; + while() { + ($dev, $data) = split(':', $_); + $_ = $dev; + if(/$NET_LIST[$n]/) { + ($net_bytes_in[$n], $net_packs_in[$n], $net_error_in[$n], undef, undef, undef, undef, undef, $net_bytes_out[$n], $net_packs_out[$n], $net_error_out[$n]) = split(' ', $data); + last; + } + } + close(IN); + } elsif($os eq "FreeBSD") { + open(IN, "netstat -nibd |"); + while() { + if(/Link/ && /$NET_LIST[$n]/) { + # Idrop column added in 8.0 + if($kernel_branch > 7.2) { + (undef, undef, undef, undef, $net_packs_in[$n], $net_error_in[$n], undef, $net_bytes_in[$n], $net_packs_out[$n], $net_error_out[$n], $net_bytes_out[$n]) = split(' ', $_); + } else { + (undef, undef, undef, undef, $net_packs_in[$n], $net_error_in[$n], $net_bytes_in[$n], $net_packs_out[$n], $net_error_out[$n], $net_bytes_out[$n]) = split(' ', $_); + } + last; + } + } + close(IN); + } elsif($os eq "OpenBSD" || $os eq "NetBSD") { + open(IN, "netstat -nibd |"); + while() { + if(/Link/ && /^$NET_LIST[$n]/) { + (undef, undef, undef, undef, $net_bytes_in[$n], $net_bytes_out[$n]) = split(' ', $_); + $net_packs_in[$n] = 0; + $net_error_in[$n] = 0; + $net_packs_out[$n] = 0; + $net_error_out[$n] = 0; + last; + } + } + close(IN); + } + } + chomp($net_bytes_in[$n], + $net_bytes_out[$n], + $net_packs_in[$n], + $net_packs_out[$n], + $net_error_in[$n], + $net_error_out[$n]); + $rrdata .= ":$net_bytes_in[$n]:$net_bytes_out[$n]:$net_packs_in[$n]:$net_packs_out[$n]:$net_error_in[$n]:$net_error_out[$n]"; + } + + RRDs::update($NET_RRD, $rrdata); + if($opt_d eq "all" || $debug) { + logger("$myself: $rrdata"); + } + my $err = RRDs::error; + logger("ERROR: while updating $NET_RRD: $err") if $err; +} + +# SERV graph +# ---------------------------------------------------------------------------- +sub serv_init { + my $myself = (caller(0))[3]; + + if(!(-e $SERV_RRD)) { + logger("Creating '$SERV_RRD' file."); + eval { + RRDs::create($SERV_RRD, + "--step=300", + "DS:serv_i_ssh:GAUGE:600:0:U", + "DS:serv_i_ftp:GAUGE:600:0:U", + "DS:serv_i_telnet:GAUGE:600:0:U", + "DS:serv_i_imap:GAUGE:600:0:U", + "DS:serv_i_smb:GAUGE:600:0:U", + "DS:serv_i_fax:GAUGE:600:0:U", + "DS:serv_i_cups:GAUGE:600:0:U", + "DS:serv_i_pop3:GAUGE:600:0:U", + "DS:serv_i_smtp:GAUGE:600:0:U", + "DS:serv_i_spam:GAUGE:600:0:U", + "DS:serv_i_virus:GAUGE:600:0:U", + "DS:serv_i_f2b:GAUGE:600:0:U", + "DS:serv_i_val02:GAUGE:600:0:U", + "DS:serv_i_val03:GAUGE:600:0:U", + "DS:serv_i_val04:GAUGE:600:0:U", + "DS:serv_i_val05:GAUGE:600:0:U", + "DS:serv_l_ssh:GAUGE:600:0:U", + "DS:serv_l_ftp:GAUGE:600:0:U", + "DS:serv_l_telnet:GAUGE:600:0:U", + "DS:serv_l_imap:GAUGE:600:0:U", + "DS:serv_l_smb:GAUGE:600:0:U", + "DS:serv_l_fax:GAUGE:600:0:U", + "DS:serv_l_cups:GAUGE:600:0:U", + "DS:serv_l_pop3:GAUGE:600:0:U", + "DS:serv_l_smtp:GAUGE:600:0:U", + "DS:serv_l_spam:GAUGE:600:0:U", + "DS:serv_l_virus:GAUGE:600:0:U", + "DS:serv_l_f2b:GAUGE:600:0:U", + "DS:serv_l_val02:GAUGE:600:0:U", + "DS:serv_l_val03:GAUGE:600:0:U", + "DS:serv_l_val04:GAUGE:600:0:U", + "DS:serv_l_val05:GAUGE:600:0:U", + "RRA:AVERAGE:0.5:1:288", + "RRA:AVERAGE:0.5:6:336", + "RRA:AVERAGE:0.5:12:744", + "RRA:AVERAGE:0.5:288:365", + "RRA:MIN:0.5:1:288", + "RRA:MIN:0.5:6:336", + "RRA:MIN:0.5:12:744", + "RRA:MIN:0.5:288:365", + "RRA:MAX:0.5:1:288", + "RRA:MAX:0.5:6:336", + "RRA:MAX:0.5:12:744", + "RRA:MAX:0.5:288:365", + "RRA:LAST:0.5:1:288", + "RRA:LAST:0.5:6:336", + "RRA:LAST:0.5:12:744", + "RRA:LAST:0.5:288:365", + ); + }; + my $err = RRDs::error; + if($@ || $err) { + logger("$@") unless !$@; + if($err) { + logger("ERROR: while creating $SERV_RRD: $err"); + if($err eq "RRDs::error") { + logger("... is the RRDtool Perl package installed?"); + } + } + return; + } + } + + # Since 2.4.1 new values are used (val_01) to support 'fail2ban' hits. + # These new values need to be renamed. + RRDs::tune($SERV_RRD, + "--data-source-rename=serv_i_val01:serv_i_f2b", + "--data-source-rename=serv_l_val01:serv_l_f2b", + ); + + our %serv_hist = (); + push(@graphs, "serv_update"); + if($opt_d eq "all" || $debug) { + logger("$myself: Ok"); + } +} + +sub serv_update { + my $myself = (caller(0))[3]; + my ($debug) = @_; + + my $ssh = 0; + my $ftp = 0; + my $telnet = 0; + my $imap = 0; + my $smb = 0; + my $fax = 0; + my $cups = 0; + my $pop3 = 0; + my $smtp = 0; + my $spam = 0; + my $virus = 0; + my $f2b = 0; + my $val02 = 0; + my $val03 = 0; + my $val04 = 0; + my $val05 = 0; + + my $date; + my $rrdata = "N"; + + # This graph is refreshed only every 5 minutes + my (undef, $min) = localtime(time); + if($min % 5) { + return; + } + + if(-r $SECURE_LOG) { + $date = strftime("%b %e", localtime); + open(IN, "$SECURE_LOG"); + while() { + if(/^$date/) { + if(/ sshd\[/ && /Accepted /) { + $ssh++; + } + if($os eq "Linux") { + if(/START: pop3/) { + $pop3++; + } + if(/START: ftp/ || + (/ proftpd\[/ && /Login successful./)) { + $ftp++; + } + if(/START: telnet/) { + $telnet++; + } + } elsif($os eq "FreeBSD") { + + if(/login:/ && /login from /) { + $telnet++; + } + } + } + } + close(IN); + } + + if(-r $IMAP_LOG) { + $IMAP_DATE_LOG_FORMAT = $IMAP_DATE_LOG_FORMAT || "%b %d"; + $date_dovecot = strftime($IMAP_DATE_LOG_FORMAT, localtime); + $date_uw = strftime("%b %e %T", localtime); + open(IN, "$IMAP_LOG"); + while() { + # UW-IMAP log + if(/$date_uw/) { + if(/ imapd\[/ && / Login user=/) { + $imap++; + } + } + # Dovecot log + if(/$date_dovecot /) { + if(/ imap-login: / && / Login: /) { + $imap++; + } + if(/ pop3-login: / && / Login: /) { + $pop3++; + } + } + } + close(IN); + } + + my $smb_L = 0; + open(IN, "smbstatus -L 2>/dev/null |"); + while() { + if(/^----------/) { + $smb_L++; + next; + } + if($smb_L) { + $smb_L++ unless !$_; + } + } + close(IN); + $smb_L--; + my $smb_S = 0; + open(IN, "smbstatus -S 2>/dev/null |"); + while() { + if(/^----------/) { + $smb_S++; + next; + } + if($smb_S) { + $smb_S++ unless !$_; + } + } + close(IN); + $smb_S--; + $smb = $smb_L + $smb_S; + + if(-r $HYLAFAX_LOG) { + $date = strftime("%m/%d/%y", localtime); + open(IN, "$HYLAFAX_LOG"); + while() { + if(/^$date/ && /SEND/) { + $fax++; + } + } + close(IN); + } + + if(-r $CUPS_LOG) { + $date = strftime("%d/%b/%Y", localtime); + open(IN, "$CUPS_LOG"); + while() { + if(/\[$date:/) { + $cups++; + } + } + close(IN); + } + + if(-r $FAIL2BAN_LOG) { + $date = strftime("%Y-%m-%d", localtime); + open(IN, $FAIL2BAN_LOG); + while() { + if(/^$date/ && / fail2ban/ && / WARNING / && / Ban /) { + $f2b++; + } + } + close(IN); + } + + if(-r $MAIL_LOG) { + $date = strftime("%b %e", localtime); + open(IN, "$MAIL_LOG"); + while() { + if(/^$date/) { + if(/to=/ && /stat(us)?=sent/i) { + $smtp++; + } + if(/MailScanner/ && /Spam Checks:/ && /Found/ && /spam messages/) { + $spam++; + } + if(/MailScanner/ && /Virus Scanning:/ && /Found/ && /viruses/) { + $virus++; + } + } + } + close(IN); + } + + $date = strftime("%Y-%m-%d", localtime); + if(-r "$CG_LOGDIR/$date.log") { + open(IN, "$CG_LOGDIR/$date.log"); + while() { + if(/DEQUEUER \[\d+\] (LOCAL\(.+\) delivered|SMTP.+ relayed)\:/) { + $smtp++; + } + if(/IMAP/ && / connected from /) { + $imap++; + } + if(/POP/ && / connected from /) { + $pop3++; + } + } + close(IN); + } + + if(-r $SPAMASSASSIN_LOG) { + $date = strftime("%b %e", localtime); + open(IN, $SPAMASSASSIN_LOG); + while() { + if(/^$date/ && /spamd: identified spam/) { + $spam++; + } + } + close(IN); + } + + if(-r $CLAMAV_LOG) { + $date = strftime("%a %b %e", localtime); + open(IN, $CLAMAV_LOG); + while() { + if(/^$date/ && / FOUND/) { + $virus++; + } + } + close(IN); + } + + # I data (incremental) + $rrdata .= ":$ssh:$ftp:$telnet:$imap:$smb:$fax:$cups:$pop3:$smtp:$spam:$virus:$f2b:$val02:$val03:$val04:$val05"; + + # L data (load) + my $l_ssh = 0; + my $l_ftp = 0; + my $l_telnet = 0; + my $l_imap = 0; + my $l_smb = 0; + my $l_fax = 0; + my $l_cups = 0; + my $l_pop3 = 0; + my $l_smtp = 0; + my $l_spam = 0; + my $l_virus = 0; + my $l_f2b = 0; + my $l_val02 = 0; + my $l_val03 = 0; + my $l_val04 = 0; + my $l_val05 = 0; + + $l_ssh = $ssh - $serv_hist{'ssh'}; + $l_ssh = 0 unless $l_ssh != $ssh; + $l_ssh /= 300; + $serv_hist{'ssh'} = $ssh; + + $l_ftp = $ftp - $serv_hist{'ftp'}; + $l_ftp = 0 unless $l_ftp != $ftp; + $l_ftp /= 300; + $serv_hist{'ftp'} = $ftp; + + $l_telnet = $telnet - $serv_hist{'telnet'}; + $l_telnet = 0 unless $l_telnet != $telnet; + $l_telnet /= 300; + $serv_hist{'telnet'} = $telnet; + + $l_imap = $imap - $serv_hist{'imap'}; + $l_imap = 0 unless $l_imap != $imap; + $l_imap /= 300; + $serv_hist{'imap'} = $imap; + + $l_smb = $smb - $serv_hist{'smb'}; + $l_smb = 0 unless $l_smb != $smb; + $l_smb /= 300; + $serv_hist{'smb'} = $smb; + + $l_fax = $fax - $serv_hist{'fax'}; + $l_fax = 0 unless $l_fax != $fax; + $l_fax /= 300; + $serv_hist{'fax'} = $fax; + + $l_cups = $cups - $serv_hist{'cups'}; + $l_cups = 0 unless $l_cups != $cups; + $l_cups /= 300; + $serv_hist{'cups'} = $cups; + + $l_pop3 = $pop3 - $serv_hist{'pop3'}; + $l_pop3 = 0 unless $l_pop3 != $pop3; + $l_pop3 /= 300; + $serv_hist{'pop3'} = $pop3; + + $l_smtp = $smtp - $serv_hist{'smtp'}; + $l_smtp = 0 unless $l_smtp != $smtp; + $l_smtp /= 300; + $serv_hist{'smtp'} = $smtp; + + $l_spam = $spam - $serv_hist{'spam'}; + $l_spam = 0 unless $l_spam != $spam; + $l_spam /= 300; + $serv_hist{'spam'} = $spam; + + $l_virus = $virus - $serv_hist{'virus'}; + $l_virus = 0 unless $l_virus != $virus; + $l_virus /= 300; + $serv_hist{'virus'} = $virus; + + $l_f2b = $f2b - $serv_hist{'f2b'}; + $l_f2b = 0 unless $l_f2b != $f2b; + $l_f2b /= 300; + $serv_hist{'f2b'} = $f2b; + + $l_val02 = $val02 - $serv_hist{'val02'}; + $l_val02 = 0 unless $l_val02 != $val02; + $l_val02 /= 300; + $serv_hist{'val02'} = $val02; + + $l_val03 = $val03 - $serv_hist{'val03'}; + $l_val03 = 0 unless $l_val03 != $val03; + $l_val03 /= 300; + $serv_hist{'val03'} = $val03; + + $l_val04 = $val04 - $serv_hist{'val04'}; + $l_val04 = 0 unless $l_val04 != $val04; + $l_val04 /= 300; + $serv_hist{'val04'} = $val04; + + $l_val05 = $val05 - $serv_hist{'val05'}; + $l_val05 = 0 unless $l_val05 != $val05; + $l_val05 /= 300; + $serv_hist{'val05'} = $val05; + + $rrdata .= ":$l_ssh:$l_ftp:$l_telnet:$l_imap:$l_smb:$l_fax:$l_cups:$l_pop3:$l_smtp:$l_spam:$l_virus:$l_f2b:$l_val02:$l_val03:$l_val04:$l_val05"; + RRDs::update($SERV_RRD, $rrdata); + if($opt_d eq "all" || $debug) { + logger("$myself: $rrdata"); + } + my $err = RRDs::error; + logger("ERROR: while updating $SERV_RRD: $err") if $err; +} + +# MAIL graph +# ---------------------------------------------------------------------------- +sub mail_init { + my $myself = (caller(0))[3]; + + if(!(-e $MAIL_RRD)) { + logger("Creating '$MAIL_RRD' file."); + eval { + RRDs::create($MAIL_RRD, + "--step=60", + "DS:mail_in:GAUGE:120:0:U", + "DS:mail_out:GAUGE:120:0:U", + "DS:mail_recvd:GAUGE:120:0:U", + "DS:mail_delvd:GAUGE:120:0:U", + "DS:mail_bytes_recvd:GAUGE:120:0:U", + "DS:mail_bytes_delvd:GAUGE:120:0:U", + "DS:mail_rejtd:GAUGE:120:0:U", + "DS:mail_spam:GAUGE:120:0:U", + "DS:mail_virus:GAUGE:120:0:U", + "DS:mail_bouncd:GAUGE:120:0:U", + "DS:mail_queued:GAUGE:120:0:U", + "DS:mail_discrd:GAUGE:120:0:U", + "DS:mail_held:GAUGE:120:0:U", + "DS:mail_forwrd:GAUGE:120:0:U", + "DS:mail_queues:GAUGE:120:0:U", + "DS:mail_val01:COUNTER:120:0:U", + "DS:mail_val02:COUNTER:120:0:U", + "DS:mail_val03:COUNTER:120:0:U", + "DS:mail_val04:COUNTER:120:0:U", + "DS:mail_val05:COUNTER:120:0:U", + "DS:mail_val06:GAUGE:120:0:U", + "DS:mail_val07:GAUGE:120:0:U", + "DS:mail_val08:GAUGE:120:0:U", + "DS:mail_val09:GAUGE:120:0:U", + "DS:mail_val10:GAUGE:120:0:U", + "RRA:AVERAGE:0.5:1:1440", + "RRA:AVERAGE:0.5:30:336", + "RRA:AVERAGE:0.5:60:744", + "RRA:AVERAGE:0.5:1440:365", + "RRA:MIN:0.5:1:1440", + "RRA:MIN:0.5:30:336", + "RRA:MIN:0.5:60:744", + "RRA:MIN:0.5:1440:365", + "RRA:MAX:0.5:1:1440", + "RRA:MAX:0.5:30:336", + "RRA:MAX:0.5:60:744", + "RRA:MAX:0.5:1440:365", + "RRA:LAST:0.5:1:1440", + "RRA:LAST:0.5:30:336", + "RRA:LAST:0.5:60:744", + "RRA:LAST:0.5:1440:365", + ); + }; + my $err = RRDs::error; + if($@ || $err) { + logger("$@") unless !$@; + if($err) { + logger("ERROR: while creating $MAIL_RRD: $err"); + if($err eq "RRDs::error") { + logger("... is the RRDtool Perl package installed?"); + } + } + return; + } + } + + # Since 2.5.0 there is support for more message status. + # Some values need to be renamed. + RRDs::tune($MAIL_RRD, + "--data-source-rename=mail_mta_val10:mail_bouncd", + "--data-source-rename=mail_mta_val12:mail_discrd", + "--data-source-rename=mail_mta_val13:mail_held", + "--data-source-rename=mail_mta_val14:mail_forwrd", + "--data-source-rename=mail_mta_val15:mail_queues", + ); + + our $mail_hist = 0; + push(@graphs, "mail_update"); + if($opt_d eq "all" || $debug) { + logger("$myself: Ok"); + } +} + +sub mail_update { + my $myself = (caller(0))[3]; + my ($debug) = @_; + + my $in_conn; + my $out_conn; + my $recvd; + my $delvd; + my $bytes_recvd; + my $bytes_delvd; + my $rejected; + my $queued; + my $spam; + my $virus; + my $gl_records; + my $gl_greylisted; + my $gl_whitelisted; + my @mta_h = (0) x 15; + my @mta = (0) x 15; + my @gen = (0) x 10; + + my $n; + my $mail_log_seekpos; + my $mail_log_size; + my $sa_log_seekpos; + my $sa_log_size; + my $clamav_log_seekpos; + my $clamav_log_size; + my $rrdata = "N"; + + # Read last MAIL data from historic + ($mail_log_seekpos, $sa_log_seekpos, $clamav_log_seekpos, @mta_h[0..15-1], @gen[0..10-1]) = split(';', $mail_hist); + $mail_log_seekpos = defined($mail_log_seekpos) ? int($mail_log_seekpos) : 0; + $sa_log_seekpos = defined($sa_log_seekpos) ? int($sa_log_seekpos) : 0; + $clamav_log_seekpos = defined($clamav_log_seekpos) ? int($clamav_log_seekpos) : 0; + + $recvd = $delvd = $bytes_recvd = $bytes_delvd = 0; + $in_conn = $out_conn = $rejected = 0; + $bounced = $discarded = $held = $forwarded = 0; + $queued = $queues = 0; + if(lc($MAIL_MTA) eq "sendmail") { + if(open(IN, "mailstats -P |")) { + while() { + if(/^ T\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/) { + $recvd = $1; + $bytes_recvd = $2; + $delvd = $3; + $bytes_delvd = $4; + } + if(/^ C\s+(\d+)\s+(\d+)\s+(\d+)/) { + $in_conn = $1; + $out_conn = $2; + $rejected = $3; + } + } + close(IN); + $bytes_recvd *= 1024; + $bytes_delvd *= 1024; + } + if(open(IN, "mailq |")) { + while() { + my ($tmp) = ($_ =~ m/^\w{14}[ *X-]\s*(\d{1,8}) /); + $queues += $tmp if $tmp; + if(/^\s+Total requests: (\d+)$/) { + $queued = $1; + } + } + close(IN); + } + } elsif(lc($MAIL_MTA) eq "postfix") { + my @data; + + for my $path (split /:/, $ENV{PATH}) { + if(-f "$path/pflogsumm" && -x _) { + open(IN, "pflogsumm -d today -h 0 -u 0 --smtpd_stats --no_bounce_detail --no_deferral_detail --no_reject_detail --no_no_msg_size --no_smtpd_warnings $MAIL_LOG 2>/dev/null |"); + } + if(-f "$path/pflogsumm.pl" && -x _) { + open(IN, "pflogsumm.pl -d today -h 0 -u 0 --smtpd_stats --no_bounce_detail --no_deferral_detail --no_reject_detail --no_no_msg_size --no_smtpd_warnings $MAIL_LOG 2>/dev/null |"); + } + } + @data = ; + close(IN); + foreach(@data) { + if(/^\s*(\d{1,7})([ km])\s*received$/) { + $recvd = $1; + $recvd = $1 * 1024 if $2 eq "k"; + $recvd = $1 * 1024 * 1024 if $2 eq "m"; + } + if(/^\s*(\d{1,7})([ km])\s*delivered$/) { + $delvd = $1; + $delvd = $1 * 1024 if $2 eq "k"; + $delvd = $1 * 1024 * 1024 if $2 eq "m"; + } + if(/^\s*(\d{1,7})([ km])\s*forwarded$/) { + $forwarded = $1; + $forwarded = $1 * 1024 if $2 eq "k"; + $forwarded = $1 * 1024 * 1024 if $2 eq "m"; + } + if(/^\s*(\d{1,7})([ km])\s*bounced$/) { + $bounced = $1; + $bounced = $1 * 1024 if $2 eq "k"; + $bounced = $1 * 1024 * 1024 if $2 eq "m"; + } + if(/^\s*(\d{1,7})([ km])\s*rejected \(/) { + $rejected = $1; + $rejected = $1 * 1024 if $2 eq "k"; + $rejected = $1 * 1024 * 1024 if $2 eq "m"; + } + if(/^\s*(\d{1,7})([ km])\s*held/) { + $held = $1; + $held = $1 * 1024 if $2 eq "k"; + $held = $1 * 1024 * 1024 if $2 eq "m"; + } + if(/^\s*(\d{1,7})([ km])\s*discarded \(/) { + $discarded = $1; + $discarded = $1 * 1024 if $2 eq "k"; + $discarded = $1 * 1024 * 1024 if $2 eq "m"; + } + if(/^\s*(\d{1,7})([ km])\s*bytes received$/) { + $bytes_recvd = $1; + $bytes_recvd = $1 * 1024 if $2 eq "k"; + $bytes_recvd = $1 * 1024 * 1024 if $2 eq "m"; + } + if(/^\s*(\d{1,7})([ km])\s*bytes delivered$/) { + $bytes_delvd = $1; + $bytes_delvd = $1 * 1024 if $2 eq "k"; + $bytes_delvd = $1 * 1024 * 1024 if $2 eq "m"; + } + } + if(open(IN, "mailq |")) { + while() { + if(/^-- (\d+) Kbytes in (\d+) Request/) { + $queues = $1; + $queued = $2; + } + } + close(IN); + } + } + + $gl_records = $gl_greylisted = $gl_whitelisted = 0; + if(lc($MAIL_GREYLIST) eq "milter-greylist") { + if(-r $MILTER_GL) { + open(IN, $MILTER_GL); + if(!seek(IN, -80, 2)) { + logger("Couldn't seek to the end ($MILTER_GL): $!"); + return; + } + while() { + if(/^# Summary:\s+(\d+) records,\s+(\d+) greylisted,\s+(\d+) whitelisted$/) { + $gl_records = $1; + $gl_greylisted = $2; + $gl_whitelisted = $3; + } + } + close(IN); + } + } + + $spam = $virus = 0; + if(-r $MAIL_LOG) { + open(IN, $MAIL_LOG); + if(!seek(IN, 0, 2)) { + logger("Couldn't seek to the end ($MAIL_LOG): $!"); + return; + } + $mail_log_size = tell(IN); + if($mail_log_size < $mail_log_seekpos) { + $mail_log_seekpos = 0; + } + if(!seek(IN, $mail_log_seekpos, 0)) { + logger("Couldn't seek to $mail_log_seekpos ($MAIL_LOG): $!"); + return; + } + while() { + my @line; + if(/MailScanner/ && /Spam Checks:/ && /Found/ && /spam messages/) { + @line = split(' ', $_); + $spam += int($line[8]); + } + if(/MailScanner/ && /Virus Scanning:/ && /Found/ && /viruses/) { + @line = split(' ', $_); + $virus += int($line[8]); + } + } + close(IN); + } + + if(-r $SPAMASSASSIN_LOG) { + $date = strftime("%b %e", localtime); + open(IN, $SPAMASSASSIN_LOG); + if(!seek(IN, 0, 2)) { + logger("Couldn't seek to the end ($SPAMASSASSIN_LOG): $!"); + return; + } + $sa_log_size = tell(IN); + if($sa_log_size < $sa_log_seekpos) { + $sa_log_seekpos = 0; + } + if(!seek(IN, $sa_log_seekpos, 0)) { + logger("Couldn't seek to $sa_log_seekpos ($SPAMASSASSIN_LOG): $!"); + return; + } + while() { + if(/^$date/ && /spamd: identified spam/) { + $spam++; + } + } + close(IN); + } + + if(-r $CLAMAV_LOG) { + $date = strftime("%a %b %e", localtime); + open(IN, $CLAMAV_LOG); + if(!seek(IN, 0, 2)) { + logger("Couldn't seek to the end ($CLAMAV_LOG): $!"); + return; + } + $clamav_log_size = tell(IN); + if($clamav_log_size < $clamav_log_seekpos) { + $clamav_log_seekpos = 0; + } + if(!seek(IN, $clamav_log_seekpos, 0)) { + logger("Couldn't seek to $clamav_log_seekpos ($CLAMAV_LOG): $!"); + return; + } + while() { + if(/^$date/ && / FOUND/) { + $virus++; + } + } + close(IN); + } + + $mta[0] = int($in_conn) - $mta_h[0]; + $mta[0] = 0 unless $mta[0] != int($in_conn); + $mta[0] /= 60; + $mta_h[0] = int($in_conn); + + $mta[1] = int($out_conn) - $mta_h[1]; + $mta[1] = 0 unless $mta[1] != int($out_conn); + $mta[1] /= 60; + $mta_h[1] = int($out_conn); + + $mta[2] = int($recvd) - $mta_h[2]; + $mta[2] = 0 unless $mta[2] != int($recvd); + $mta[2] /= 60; + $mta_h[2] = int($recvd); + + $mta[3] = int($delvd) - $mta_h[3]; + $mta[3] = 0 unless $mta[3] != int($delvd); + $mta[3] /= 60; + $mta_h[3] = int($delvd); + + $mta[4] = int($bytes_recvd) - $mta_h[4]; + $mta[4] = 0 unless $mta[4] != int($bytes_recvd); + $mta[4] /= 60; + $mta_h[4] = int($bytes_recvd); + + $mta[5] = int($bytes_delvd) - $mta_h[5]; + $mta[5] = 0 unless $mta[5] != int($bytes_delvd); + $mta[5] /= 60; + $mta_h[5] = int($bytes_delvd); + + $mta[6] = int($rejected) - $mta_h[6]; + $mta[6] = 0 unless $mta[6] != int($rejected); + $mta[6] /= 60; + $mta_h[6] = int($rejected); + + # avoid initial spike + $mta[7] = int($spam) unless !$mta_h[7]; + $mta_h[7] = int($spam) unless $mta_h[7]; + $mta[7] /= 60; + + # avoid initial spike + $mta[8] = int($virus) unless !$mta_h[8]; + $mta_h[8] = int($virus) unless $mta_h[8]; + $mta[8] /= 60; + + $mta[9] = int($bouncd) - $mta_h[9]; + $mta[9] = 0 unless $mta[9] != int($bouncd); + $mta[9] /= 60; + $mta_h[9] = int($bouncd); + + $mta[10] = int($queued); + + $mta[11] = int($discrd) - $mta_h[11]; + $mta[11] = 0 unless $mta[11] != int($discrd); + $mta[11] /= 60; + $mta_h[11] = int($discrd); + + $mta[12] = int($held) - $mta_h[12]; + $mta[12] = 0 unless $mta[12] != int($held); + $mta[12] /= 60; + $mta_h[12] = int($held); + + $mta[13] = int($forwrd) - $mta_h[13]; + $mta[13] = 0 unless $mta[13] != int($forwrd); + $mta[13] /= 60; + $mta_h[13] = int($forwrd); + + $mta[14] = int($queues); + + $gen[6] = int($gl_records); + $gen[7] = int($gl_greylisted); + $gen[8] = int($gl_whitelisted); + + $mail_hist = join(";", $mail_log_size, $sa_log_size, $clamav_log_size, @mta_h, @gen); + for($n = 0; $n < 15; $n++) { + $rrdata .= ":" . $mta[$n]; + } + for($n = 0; $n < 10; $n++) { + $rrdata .= ":" . $gen[$n]; + } + + RRDs::update($MAIL_RRD, $rrdata); + if($opt_d eq "all" || $debug) { + logger("$myself: $rrdata"); + } + my $err = RRDs::error; + logger("ERROR: while updating $MAIL_RRD: $err") if $err; +} + +# PORT graph +# ---------------------------------------------------------------------------- +sub port_init { + my $myself = (caller(0))[3]; + + my $info; + my @ds; + my @tmp; + my @data; + my $n; + my $p; + + if(-e $PORT_RRD) { + $info = RRDs::info($PORT_RRD); + for my $key (keys %$info) { + if(index($key, 'ds[') == 0) { + if(index($key, '.type') != -1) { + push(@ds, substr($key, 3, index($key, ']') - 3)); + } + } + } + if(scalar(@ds) / 2 != $PORT_MAX) { + logger("Detected size mismatch between \$PORT_MAX ($PORT_MAX) and $PORT_RRD (" . scalar(@ds) / 2 . "). Resizing it accordingly. All historic data will be lost. Backup file created."); + rename($PORT_RRD, "$PORT_RRD.bak"); + } + } + + if(!(-e $PORT_RRD)) { + logger("Creating '$PORT_RRD' file."); + for($n = 0; $n < $PORT_MAX; $n++) { + push(@tmp, "DS:port" . $n . "_in:GAUGE:120:0:U"); + push(@tmp, "DS:port" . $n . "_out:GAUGE:120:0:U"); + } + eval { + RRDs::create($PORT_RRD, + "--step=60", + @tmp, + "RRA:AVERAGE:0.5:1:1440", + "RRA:AVERAGE:0.5:30:336", + "RRA:AVERAGE:0.5:60:744", + "RRA:AVERAGE:0.5:1440:365", + "RRA:MIN:0.5:1:1440", + "RRA:MIN:0.5:30:336", + "RRA:MIN:0.5:60:744", + "RRA:MIN:0.5:1440:365", + "RRA:MAX:0.5:1:1440", + "RRA:MAX:0.5:30:336", + "RRA:MAX:0.5:60:744", + "RRA:MAX:0.5:1440:365", + "RRA:LAST:0.5:1:1440", + "RRA:LAST:0.5:30:336", + "RRA:LAST:0.5:60:744", + "RRA:LAST:0.5:1440:365", + ); + }; + my $err = RRDs::error; + if($@ || $err) { + logger("$@") unless !$@; + if($err) { + logger("ERROR: while creating $PORT_RRD: $err"); + if($err eq "RRDs::error") { + logger("... is the RRDtool Perl package installed?"); + } + } + return; + } + } + + if($os eq "Linux") { + my $num; + my @line; + + # set the iptables rules for each defined port + for($n = 0; $n < $PORT_MAX; $n++) { + if($PORT_LIST[$n]) { + $p = lc($PORT_PROT[$n]); + $p = "all" unless $PORT_PROT[$n]; + system("iptables -N MONITORIX_IN_$n 2>/dev/null"); + system("iptables -I INPUT -p $p --dport $PORT_LIST[$n] -j MONITORIX_IN_$n -c 0 0"); + system("iptables -N MONITORIX_OUT_$n 2>/dev/null"); + system("iptables -I OUTPUT -p $p --sport $PORT_LIST[$n] -j MONITORIX_OUT_$n -c 0 0"); + } + } + } + if($os eq "FreeBSD" || $os eq "OpenBSD") { + # set the ipfw rules for each defined port + for($n = 0; $n < $PORT_MAX; $n++) { + if($PORT_LIST[$n]) { + $p = lc($PORT_PROT[$n]); + $p = "ip" unless $PORT_PROT[$n]; + system("ipfw -q add $PORT_RULE count $p from me $PORT_LIST[$n] to any"); + system("ipfw -q add $PORT_RULE count $p from any to me $PORT_LIST[$n]"); + } + } + } + + # Since 2.5.2 port values need to be converted to GAUGE. + for($n = 0; $n < $PORT_MAX; $n++) { + RRDs::tune($PORT_RRD, + "--data-source-type=port" . $n . "_in:GAUGE", + "--data-source-type=port" . $n . "_out:GAUGE", + ); + } + + our @port_hist_in = (); + our @port_hist_out = (); + push(@graphs, "port_update"); + if($opt_d eq "all" || $debug) { + logger("$myself: Ok"); + } +} + +sub port_update { + my $myself = (caller(0))[3]; + my ($debug) = @_; + + my @in; + my @out; + + my $n; + my $rrdata = "N"; + + if($os eq "Linux") { + open(IN, "iptables -nxvL INPUT |"); + while() { + for($n = 0; $n < $PORT_MAX; $n++) { + $in[$n] = 0 unless $in[$n]; + if(/ MONITORIX_IN_$n /) { + my (undef, $bytes) = split(' ', $_); + chomp($bytes); + $in[$n] = $bytes - $port_hist_in[$n]; + $in[$n] = 0 unless $in[$n] != $bytes; + $port_hist_in[$n] = $bytes; + $in[$n] /= 60; + } + } + } + close(IN); + open(IN, "iptables -nxvL OUTPUT |"); + while() { + for($n = 0; $n < $PORT_MAX; $n++) { + $out[$n] = 0 unless $out[$n]; + if(/ MONITORIX_OUT_$n /) { + my (undef, $bytes) = split(' ', $_); + chomp($bytes); + $out[$n] = $bytes - $port_hist_out[$n]; + $out[$n] = 0 unless $out[$n] != $bytes; + $port_hist_out[$n] = $bytes; + $out[$n] /= 60; + } + } + } + close(IN); + } + if($os eq "FreeBSD" || $os eq "OpenBSD") { + open(IN, "ipfw show $PORT_RULE 2>/dev/null |"); + while() { + for($n = 0; $n < $PORT_MAX; $n++) { + $in[$n] = 0 unless $in[$n]; + if(/ from any to me dst-port $PORT_LIST[$n]$/) { + my (undef, undef, $bytes) = split(' ', $_); + chomp($bytes); + $in[$n] = $bytes; + } + $out[$n] = 0 unless $out[$n]; + if(/ from me $PORT_LIST[$n] to any$/) { + my (undef, undef, $bytes) = split(' ', $_); + chomp($bytes); + $out[$n] = $bytes; + } + } + } + close(IN); + } + + for($n = 0; $n < $PORT_MAX; $n++) { + $rrdata .= ":$in[$n]:$out[$n]"; + } + RRDs::update($PORT_RRD, $rrdata); + if($opt_d eq "all" || $debug) { + logger("$myself: $rrdata"); + } + my $err = RRDs::error; + logger("ERROR: while updating $PORT_RRD: $err") if $err; +} + +# USER graph +# ---------------------------------------------------------------------------- +sub user_init { + my $myself = (caller(0))[3]; + + if(!(-e $USER_RRD)) { + logger("Creating '$USER_RRD' file."); + eval { + RRDs::create($USER_RRD, + "--step=60", + "DS:user_sys:GAUGE:120:0:U", + "DS:user_smb:GAUGE:120:0:U", + "DS:user_mac:GAUGE:120:0:U", + "DS:user_val1:GAUGE:120:0:U", + "DS:user_val2:GAUGE:120:0:U", + "DS:user_val3:GAUGE:120:0:U", + "DS:user_val4:GAUGE:120:0:U", + "DS:user_val5:GAUGE:120:0:U", + "RRA:AVERAGE:0.5:1:1440", + "RRA:AVERAGE:0.5:30:336", + "RRA:AVERAGE:0.5:60:744", + "RRA:AVERAGE:0.5:1440:365", + "RRA:MIN:0.5:1:1440", + "RRA:MIN:0.5:30:336", + "RRA:MIN:0.5:60:744", + "RRA:MIN:0.5:1440:365", + "RRA:MAX:0.5:1:1440", + "RRA:MAX:0.5:30:336", + "RRA:MAX:0.5:60:744", + "RRA:MAX:0.5:1440:365", + "RRA:LAST:0.5:1:1440", + "RRA:LAST:0.5:30:336", + "RRA:LAST:0.5:60:744", + "RRA:LAST:0.5:1440:365", + ); + }; + my $err = RRDs::error; + if($@ || $err) { + logger("$@") unless !$@; + if($err) { + logger("ERROR: while creating $USER_RRD: $err"); + if($err eq "RRDs::error") { + logger("... is the RRDtool Perl package installed?"); + } + } + return; + } + } + + push(@graphs, "user_update"); + if($opt_d eq "all" || $debug) { + logger("$myself: Ok"); + } +} + +sub user_update { + my $myself = (caller(0))[3]; + my ($debug) = @_; + + my $sys; + my $smb; + my $mac; + + my @data; + my $rrdata = "N"; + + open(IN, "who -q |"); + while() { + if(/^#/) { + my @tmp = split('=', $_); + $sys = $tmp[scalar(@tmp) - 1]; + chomp($sys); + $sys = int($sys); + last; + } + } + close(IN); + + $smb = 0; + open(IN, "smbstatus -b 2>/dev/null |"); + while() { + if(/^----------/) { + $smb++; + next; + } + if($smb) { + $smb++ unless !$_; + } + } + close(IN); + $smb--; + + open(IN, "macusers 2>/dev/null |"); + @data = ; + close(IN); + $mac = scalar(@data) - 1; + $mac = 0 unless @data; + + $rrdata .= ":$sys:$smb:$mac:0:0:0:0:0"; + RRDs::update($USER_RRD, $rrdata); + if($opt_d eq "all" || $debug) { + logger("$myself: $rrdata"); + } + my $err = RRDs::error; + logger("ERROR: while updating $USER_RRD: $err") if $err; +} + +# APACHE graph +# ---------------------------------------------------------------------------- +sub apache_init { + my $myself = (caller(0))[3]; + + my $info; + my @ds; + my @tmp; + my $n; + + if(!defined(@APACHE_LIST)) { + logger("$myself: ERROR: missing or not defined APACHE_LIST option."); + return 0; + } + + if(-e $APACHE_RRD) { + $info = RRDs::info($APACHE_RRD); + for my $key (keys %$info) { + if(index($key, 'ds[') == 0) { + if(index($key, '.type') != -1) { + push(@ds, substr($key, 3, index($key, ']') - 3)); + } + } + } + if(scalar(@ds) / 5 != scalar(@APACHE_LIST)) { + logger("Detected size mismatch between \@APACHE_LIST (" . scalar(@APACHE_LIST) . ") and $APACHE_RRD (" . scalar(@ds) / 5 . "). Resizing it accordingly. All historic data will be lost. Backup file created."); + rename($APACHE_RRD, "$APACHE_RRD.bak"); + } + } + + if(!(-e $APACHE_RRD)) { + logger("Creating '$APACHE_RRD' file."); + for($n = 0; $n < scalar(@APACHE_LIST); $n++) { + push(@tmp, "DS:apache" . $n . "_acc:GAUGE:120:0:U"); + push(@tmp, "DS:apache" . $n . "_kb:GAUGE:120:0:U"); + push(@tmp, "DS:apache" . $n . "_cpu:GAUGE:120:0:U"); + push(@tmp, "DS:apache" . $n . "_busy:GAUGE:120:0:U"); + push(@tmp, "DS:apache" . $n . "_idle:GAUGE:120:0:U"); + } + eval { + RRDs::create($APACHE_RRD, + "--step=60", + @tmp, + "RRA:AVERAGE:0.5:1:1440", + "RRA:AVERAGE:0.5:30:336", + "RRA:AVERAGE:0.5:60:744", + "RRA:AVERAGE:0.5:1440:365", + "RRA:MIN:0.5:1:1440", + "RRA:MIN:0.5:30:336", + "RRA:MIN:0.5:60:744", + "RRA:MIN:0.5:1440:365", + "RRA:MAX:0.5:1:1440", + "RRA:MAX:0.5:30:336", + "RRA:MAX:0.5:60:744", + "RRA:MAX:0.5:1440:365", + "RRA:LAST:0.5:1:1440", + "RRA:LAST:0.5:30:336", + "RRA:LAST:0.5:60:744", + "RRA:LAST:0.5:1440:365", + ); + }; + my $err = RRDs::error; + if($@ || $err) { + logger("$@") unless !$@; + if($err) { + logger("ERROR: while creating $APACHE_RRD: $err"); + if($err eq "RRDs::error") { + logger("... is the RRDtool Perl package installed?"); + } + } + return; + } + } + + # Since 2.5.0 first 5 values belong to the first Apache being monitored. + # These values need to be renamed. + RRDs::tune($APACHE_RRD, + "--data-source-rename=apache_acc:apache0_acc", + "--data-source-rename=apache_kb:apache0_kb", + "--data-source-rename=apache_cpu:apache0_cpu", + "--data-source-rename=apache_busy:apache0_busy", + "--data-source-rename=apache_idle:apache0_idle", + ); + + our %apache_hist = (); + push(@graphs, "apache_update"); + if($opt_d eq "all" || $debug) { + logger("$myself: Ok"); + } +} + +sub apache_update { + my $myself = (caller(0))[3]; + my ($debug) = @_; + + my $acc; + my $kb; + my $cpu; + my $busy; + my $idle; + + my $str; + my $rrdata = "N"; + + my $n = 0; + foreach(@APACHE_LIST) { + my $URL = $_ . "/server-status?auto"; + my $ua = LWP::UserAgent->new(timeout => 30); + my $response = $ua->request(HTTP::Request->new('GET', $URL)); + + foreach(split('\n', $response->content)) { + if(/^Total Accesses:\s+(\d+)$/) { + $str = $n . "acc"; + $acc = $1 - $apache_hist{$str}; + $acc = 0 unless $acc != $1; + $acc /= 60; + $apache_hist{$str} = $1; + next; + } + if(/^Total kBytes:\s+(\d+)$/) { + $str = $n . "kb"; + $kb = $1 - $apache_hist{$str}; + $kb = 0 unless $kb != $1; + $apache_hist{$str} = $1; + next; + } + if(/^CPULoad:\s+(\d*\.\d+)$/) { + $cpu = abs($1); + next; + } + if(/^BusyWorkers:\s+(\d+)/ || /^BusyServers:\s+(\d+)/) { + $busy = int($1); + next; + } + if(/^IdleWorkers:\s+(\d+)/ || /^IdleServers:\s+(\d+)/) { + $idle = int($1); + last; + } + } + $rrdata .= ":$acc:$kb:$cpu:$busy:$idle"; + $n++; + } + + RRDs::update($APACHE_RRD, $rrdata); + if($opt_d eq "all" || $debug) { + logger("$myself: $rrdata"); + } + my $err = RRDs::error; + logger("ERROR: while updating $APACHE_RRD: $err") if $err; +} + +# NGINX graph +# ---------------------------------------------------------------------------- +sub nginx_init { + my $myself = (caller(0))[3]; + + + if(!(-e $NGINX_RRD)) { + logger("Creating '$NGINX_RRD' file."); + eval { + RRDs::create($NGINX_RRD, + "--step=60", + "DS:nginx_requests:GAUGE:120:0:U", + "DS:nginx_total:GAUGE:120:0:U", + "DS:nginx_reading:GAUGE:120:0:U", + "DS:nginx_writing:GAUGE:120:0:U", + "DS:nginx_waiting:GAUGE:120:0:U", + "DS:nginx_bytes_in:GAUGE:120:0:U", + "DS:nginx_bytes_out:GAUGE:120:0:U", + "RRA:AVERAGE:0.5:1:1440", + "RRA:AVERAGE:0.5:30:336", + "RRA:AVERAGE:0.5:60:744", + "RRA:AVERAGE:0.5:1440:365", + "RRA:MIN:0.5:1:1440", + "RRA:MIN:0.5:30:336", + "RRA:MIN:0.5:60:744", + "RRA:MIN:0.5:1440:365", + "RRA:MAX:0.5:1:1440", + "RRA:MAX:0.5:30:336", + "RRA:MAX:0.5:60:744", + "RRA:MAX:0.5:1440:365", + "RRA:LAST:0.5:1:1440", + "RRA:LAST:0.5:30:336", + "RRA:LAST:0.5:60:744", + "RRA:LAST:0.5:1440:365", + ); + }; + my $err = RRDs::error; + if($@ || $err) { + logger("$@") unless !$@; + if($err) { + logger("ERROR: while creating $NGINX_RRD: $err"); + if($err eq "RRDs::error") { + logger("... is the RRDtool Perl package installed?"); + } + } + return; + } + } + + if(!defined($NGINX_PORT)) { + logger("$myself: ERROR: undefined NGINX_PORT option."); + return 0; + } + + if($os eq "Linux") { + system("iptables -N NGINX_IN 2>/dev/null"); + system("iptables -I INPUT -p tcp --dport $NGINX_PORT -j NGINX_IN -c 0 0"); + system("iptables -N NGINX_OUT 2>/dev/null"); + system("iptables -I OUTPUT -p tcp --sport $NGINX_PORT -j NGINX_OUT -c 0 0"); + } + if($os eq "FreeBSD" || $os eq "OpenBSD") { + system("ipfw delete $NGINX_RULE 2>/dev/null"); + system("ipfw -q add $NGINX_RULE count tcp from me $NGINX_PORT to any"); + system("ipfw -q add $NGINX_RULE count tcp from any to me $NGINX_PORT"); + } + + # Since 2.4.0 these two values need to be converted to GAUGE. + RRDs::tune($NGINX_RRD, + "--data-source-type=nginx_bytes_in:GAUGE", + "--data-source-type=nginx_bytes_out:GAUGE", + ); + + our %nginx_hist = (); + push(@graphs, "nginx_update"); + if($opt_d eq "all" || $debug) { + logger("$myself: Ok"); + } +} + +sub nginx_update { + my $myself = (caller(0))[3]; + my ($debug) = @_; + + my $reqs; + my $tot; + my $reads; + my $writes; + my $waits; + my $in; + my $out; + my $val; + + my $URL = "http://127.0.0.1:" . $NGINX_PORT . "/nginx_status"; + my $ua = LWP::UserAgent->new(timeout => 30); + my $response = $ua->request(HTTP::Request->new('GET', $URL)); + my $rrdata = "N"; + + foreach(split('\n', $response->content)) { + if(/^Active connections:\s+(\d+)\s*/) { + $tot = $1; + next; + } + if(/^\s+(\d+)\s+(\d+)\s+(\d+)\s*/) { + $reqs = $3 - $nginx_hist{'requests'}; + $reqs = 0 unless $reqs != $3; + $nginx_hist{'requests'} = $3; + } + if(/^Reading:\s+(\d+).*Writing:\s+(\d+).*Waiting:\s+(\d+)\s*/) { + $reads = $1; + $writes = $2; + $waits = $3; + } + } + + if($os eq "Linux") { + open(IN, "iptables -nxvL INPUT |"); + while() { + if(/ NGINX_IN /) { + (undef, $val) = split(' ', $_); + chomp($val); + $in = $val - $nginx_hist{'in'}; + $in = 0 unless $in != $val; + $nginx_hist{'in'} = $val; + $in /= 60; + last; + } + } + close(IN); + open(IN, "iptables -nxvL OUTPUT |"); + while() { + if(/ NGINX_OUT /) { + (undef, $val) = split(' ', $_); + chomp($val); + $out = $val - $nginx_hist{'out'}; + $out = 0 unless $out != $val; + $nginx_hist{'out'} = $val; + $out /= 60; + last; + } + } + close(IN); + } + if($os eq "FreeBSD" || $os eq "OpenBSD") { + open(IN, "ipfw show $NGINX_RULE 2>/dev/null |"); + while() { + if(/ from any to me dst-port $NGINX_PORT$/) { + (undef, undef, $val) = split(' ', $_); + chomp($val); + $in = $val - $nginx_hist{'in'}; + $in = 0 unless $in != $val; + $nginx_hist{'in'} = $val; + $in /= 60; + } + if(/ from me $NGINX_PORT to any$/) { + (undef, undef, $val) = split(' ', $_); + chomp($val); + $out = $val - $nginx_hist{'out'}; + $out = 0 unless $out != $val; + $nginx_hist{'out'} = $val; + $out /= 60; + } + } + close(IN); + } + + $rrdata .= ":$reqs:$tot:$reads:$writes:$waits:$in:$out"; + RRDs::update($NGINX_RRD, $rrdata); + if($opt_d eq "all" || $debug) { + logger("$myself: $rrdata"); + } + my $err = RRDs::error; + logger("ERROR: while updating $NGINX_RRD: $err") if $err; +} + +# LIGHTTPD graph +# ---------------------------------------------------------------------------- +sub lighttpd_init { + my $myself = (caller(0))[3]; + + my $info; + my @ds; + my @tmp; + my $n; + + if(!defined(@LIGHTTPD_LIST)) { + logger("$myself: ERROR: missing or not defined LIGHTTPD_LIST option."); + return 0; + } + + if(-e $LIGHTTPD_RRD) { + $info = RRDs::info($LIGHTTPD_RRD); + for my $key (keys %$info) { + if(index($key, 'ds[') == 0) { + if(index($key, '.type') != -1) { + push(@ds, substr($key, 3, index($key, ']') - 3)); + } + } + } + if(scalar(@ds) / 9 != scalar(@LIGHTTPD_LIST)) { + logger("Detected size mismatch between \@LIGHTTPD_LIST (" . scalar(@LIGHTTPD_LIST) . ") and $LIGHTTPD_RRD (" . scalar(@ds) / 9 . "). Resizing it accordingly. All historic data will be lost. Backup file created."); + rename($LIGHTTPD_RRD, "$LIGHTTPD_RRD.bak"); + } + } + + if(!(-e $LIGHTTPD_RRD)) { + logger("Creating '$LIGHTTPD_RRD' file."); + for($n = 0; $n < scalar(@LIGHTTPD_LIST); $n++) { + push(@tmp, "DS:lighttpd" . $n . "_acc:GAUGE:120:0:U"); + push(@tmp, "DS:lighttpd" . $n . "_kb:GAUGE:120:0:U"); + push(@tmp, "DS:lighttpd" . $n . "_busy:GAUGE:120:0:U"); + push(@tmp, "DS:lighttpd" . $n . "_idle:GAUGE:120:0:U"); + push(@tmp, "DS:lighttpd" . $n . "_val01:GAUGE:120:0:U"); + push(@tmp, "DS:lighttpd" . $n . "_val02:GAUGE:120:0:U"); + push(@tmp, "DS:lighttpd" . $n . "_val03:GAUGE:120:0:U"); + push(@tmp, "DS:lighttpd" . $n . "_val04:GAUGE:120:0:U"); + push(@tmp, "DS:lighttpd" . $n . "_val05:GAUGE:120:0:U"); + } + eval { + RRDs::create($LIGHTTPD_RRD, + "--step=60", + @tmp, + "RRA:AVERAGE:0.5:1:1440", + "RRA:AVERAGE:0.5:30:336", + "RRA:AVERAGE:0.5:60:744", + "RRA:AVERAGE:0.5:1440:365", + "RRA:MIN:0.5:1:1440", + "RRA:MIN:0.5:30:336", + "RRA:MIN:0.5:60:744", + "RRA:MIN:0.5:1440:365", + "RRA:MAX:0.5:1:1440", + "RRA:MAX:0.5:30:336", + "RRA:MAX:0.5:60:744", + "RRA:MAX:0.5:1440:365", + "RRA:LAST:0.5:1:1440", + "RRA:LAST:0.5:30:336", + "RRA:LAST:0.5:60:744", + "RRA:LAST:0.5:1440:365", + ); + }; + my $err = RRDs::error; + if($@ || $err) { + logger("$@") unless !$@; + if($err) { + logger("ERROR: while creating $LIGHTTPD_RRD: $err"); + if($err eq "RRDs::error") { + logger("... is the RRDtool Perl package installed?"); + } + } + return; + } + } + + our %lighttpd_hist = (); + push(@graphs, "lighttpd_update"); + if($opt_d eq "all" || $debug) { + logger("$myself: Ok"); + } +} + +sub lighttpd_update { + my $myself = (caller(0))[3]; + my ($debug) = @_; + + my $acc; + my $kb; + my $busy; + my $idle; + + my $str; + my $rrdata = "N"; + + my $n = 0; + foreach(@LIGHTTPD_LIST) { + my $URL = $_ . "/server-status?auto"; + my $ua = LWP::UserAgent->new(timeout => 30); + my $response = $ua->request(HTTP::Request->new('GET', $URL)); + + foreach(split('\n', $response->content)) { + if(/^Total Accesses:\s+(\d+)$/) { + $str = $n . "acc"; + $acc = $1 - $lighttpd_hist{$str}; + $acc = 0 unless $acc != $1; + $acc /= 60; + $lighttpd_hist{$str} = $1; + next; + } + if(/^Total kBytes:\s+(\d+)$/) { + $str = $n . "kb"; + $kb = $1 - $lighttpd_hist{$str}; + $kb = 0 unless $kb != $1; + $lighttpd_hist{$str} = $1; + next; + } + if(/^BusyServers:\s+(\d+)/) { + $busy = int($1); + next; + } + if(/^IdleServers:\s+(\d+)/) { + $idle = int($1); + last; + } + } + $rrdata .= ":$acc:$kb:$busy:$idle:0:0:0:0:0"; + $n++; + } + + RRDs::update($LIGHTTPD_RRD, $rrdata); + if($opt_d eq "all" || $debug) { + logger("$myself: $rrdata"); + } + my $err = RRDs::error; + logger("ERROR: while updating $LIGHTTPD_RRD: $err") if $err; +} + +# MYSQL graph +# ---------------------------------------------------------------------------- +sub mysql_init { + my $myself = (caller(0))[3]; + + my $info; + my @ds; + my @tmp; + my $num; + my $n; + + $MYSQL_CONN_TYPE = $MYSQL_CONN_TYPE || "Host"; + if(lc($MYSQL_CONN_TYPE) eq "host") { + $num = scalar(@MYSQL_HOST_LIST); + if(!@MYSQL_HOST_LIST) { + logger("$myself: ERROR: invalid value or not defined MYSQL_HOST_LIST option."); + return 0; + } + if(!@MYSQL_PORT_LIST) { + logger("$myself: ERROR: invalid value or not defined MYSQL_PORT_LIST option."); + return 0; + } + if(!@MYSQL_USER_LIST) { + logger("$myself: ERROR: invalid value or not defined MYSQL_USER_LIST option."); + return 0; + } + if(!@MYSQL_PASS_LIST) { + logger("$myself: ERROR: invalid value or not defined MYSQL_PASS_LIST option."); + return 0; + } + } elsif(lc($MYSQL_CONN_TYPE) eq "socket") { + $num = scalar(@MYSQL_SOCK_LIST); + if(!@MYSQL_SOCK_LIST) { + logger("$myself: ERROR: invalid value or not defined MYSQL_SOCK_LIST option."); + return 0; + } + } else { + logger("$myself: ERROR: invalid value in MYSQL_CONN_TYPE option."); + return 0; + } + + if(-e $MYSQL_RRD) { + $info = RRDs::info($MYSQL_RRD); + for my $key (keys %$info) { + if(index($key, 'ds[') == 0) { + if(index($key, '.type') != -1) { + push(@ds, substr($key, 3, index($key, ']') - 3)); + } + } + } + if(lc($MYSQL_CONN_TYPE) eq "host") { + if(scalar(@ds) / 38 != scalar(@MYSQL_HOST_LIST)) { + logger("Detected size mismatch between \@MYSQL_HOST_LIST (" . scalar(@MYSQL_HOST_LIST) . ") and $MYSQL_RRD (" . scalar(@ds) / 38 . "). Resizing it accordingly. All historic data will be lost. Backup file created."); + rename($MYSQL_RRD, "$MYSQL_RRD.bak"); + } + } + if(lc($MYSQL_CONN_TYPE) eq "socket") { + if(scalar(@ds) / 38 != scalar(@MYSQL_SOCK_LIST)) { + logger("Detected size mismatch between \@MYSQL_SOCK_LIST (" . scalar(@MYSQL_SOCK_LIST) . ") and $MYSQL_RRD (" . scalar(@ds) / 38 . "). Resizing it accordingly. All historic data will be lost. Backup file created."); + rename($MYSQL_RRD, "$MYSQL_RRD.bak"); + } + } + } + + if(!(-e $MYSQL_RRD)) { + logger("Creating '$MYSQL_RRD' file."); + for($n = 0; $n < $num; $n++) { + push(@tmp, "DS:mysql" . $n . "_queries:GAUGE:120:0:U"); + push(@tmp, "DS:mysql" . $n . "_sq:GAUGE:120:0:U"); + push(@tmp, "DS:mysql" . $n . "_tchr:GAUGE:120:0:100"); + push(@tmp, "DS:mysql" . $n . "_qcu:GAUGE:120:0:100"); + push(@tmp, "DS:mysql" . $n . "_ot:GAUGE:120:0:U"); + push(@tmp, "DS:mysql" . $n . "_conns_u:GAUGE:120:0:100"); + push(@tmp, "DS:mysql" . $n . "_conns:GAUGE:120:0:U"); + push(@tmp, "DS:mysql" . $n . "_tlw:GAUGE:120:0:U"); + push(@tmp, "DS:mysql" . $n . "_kbu:GAUGE:120:0:100"); + push(@tmp, "DS:mysql" . $n . "_innbu:GAUGE:120:0:100"); + push(@tmp, "DS:mysql" . $n . "_csel:GAUGE:120:0:U"); + push(@tmp, "DS:mysql" . $n . "_ccom:GAUGE:120:0:U"); + push(@tmp, "DS:mysql" . $n . "_cdel:GAUGE:120:0:U"); + push(@tmp, "DS:mysql" . $n . "_cins:GAUGE:120:0:U"); + push(@tmp, "DS:mysql" . $n . "_cinss:GAUGE:120:0:U"); + push(@tmp, "DS:mysql" . $n . "_cupd:GAUGE:120:0:U"); + push(@tmp, "DS:mysql" . $n . "_crep:GAUGE:120:0:U"); + push(@tmp, "DS:mysql" . $n . "_creps:GAUGE:120:0:U"); + push(@tmp, "DS:mysql" . $n . "_crol:GAUGE:120:0:U"); + push(@tmp, "DS:mysql" . $n . "_acli:GAUGE:120:0:U"); + push(@tmp, "DS:mysql" . $n . "_acon:GAUGE:120:0:U"); + push(@tmp, "DS:mysql" . $n . "_brecv:GAUGE:120:0:U"); + push(@tmp, "DS:mysql" . $n . "_bsent:GAUGE:120:0:U"); + push(@tmp, "DS:mysql" . $n . "_val01:GAUGE:120:0:U"); + push(@tmp, "DS:mysql" . $n . "_val02:GAUGE:120:0:U"); + push(@tmp, "DS:mysql" . $n . "_val03:GAUGE:120:0:U"); + push(@tmp, "DS:mysql" . $n . "_val04:GAUGE:120:0:U"); + push(@tmp, "DS:mysql" . $n . "_val05:GAUGE:120:0:U"); + push(@tmp, "DS:mysql" . $n . "_val06:GAUGE:120:0:U"); + push(@tmp, "DS:mysql" . $n . "_val07:GAUGE:120:0:U"); + push(@tmp, "DS:mysql" . $n . "_val08:GAUGE:120:0:U"); + push(@tmp, "DS:mysql" . $n . "_val09:GAUGE:120:0:U"); + push(@tmp, "DS:mysql" . $n . "_val10:GAUGE:120:0:U"); + push(@tmp, "DS:mysql" . $n . "_val11:GAUGE:120:0:U"); + push(@tmp, "DS:mysql" . $n . "_val12:GAUGE:120:0:U"); + push(@tmp, "DS:mysql" . $n . "_val13:GAUGE:120:0:U"); + push(@tmp, "DS:mysql" . $n . "_val14:GAUGE:120:0:U"); + push(@tmp, "DS:mysql" . $n . "_val15:GAUGE:120:0:U"); + } + eval { + RRDs::create($MYSQL_RRD, + "--step=60", + @tmp, + "RRA:AVERAGE:0.5:1:1440", + "RRA:AVERAGE:0.5:30:336", + "RRA:AVERAGE:0.5:60:744", + "RRA:AVERAGE:0.5:1440:365", + "RRA:MIN:0.5:1:1440", + "RRA:MIN:0.5:30:336", + "RRA:MIN:0.5:60:744", + "RRA:MIN:0.5:1440:365", + "RRA:MAX:0.5:1:1440", + "RRA:MAX:0.5:30:336", + "RRA:MAX:0.5:60:744", + "RRA:MAX:0.5:1440:365", + "RRA:LAST:0.5:1:1440", + "RRA:LAST:0.5:30:336", + "RRA:LAST:0.5:60:744", + "RRA:LAST:0.5:1440:365", + ); + }; + my $err = RRDs::error; + if($@ || $err) { + logger("$@") unless !$@; + if($err) { + logger("ERROR: while creating $MYSQL_RRD: $err"); + if($err eq "RRDs::error") { + logger("... is the RRDtool Perl package installed?"); + } + } + return; + } + } + + # Since 2.5.0 first NN values belong to the first MySQL being monitored. + # These values need to be renamed. + RRDs::tune($MYSQL_RRD, + "--data-source-rename=mysql_queries:mysql0_queries", + "--data-source-rename=mysql_slow_queries:mysql0_sq", + "--data-source-rename=mysql_tcache_hit_r:mysql0_tchr", + "--data-source-rename=mysql_qcache_usage:mysql0_qcu", + "--data-source-rename=mysql_opened_tbl:mysql0_ot", + "--data-source-rename=mysql_conns_u:mysql0_conns_u", + "--data-source-rename=mysql_conns:mysql0_conns", + "--data-source-rename=mysql_tlocks_w:mysql0_tlw", + "--data-source-rename=mysql_key_buf_u:mysql0_kbu", + "--data-source-rename=mysql_innodb_buf_u:mysql0_innbu", + "--data-source-rename=mysql_com_select:mysql0_csel", + "--data-source-rename=mysql_com_commit:mysql0_ccom", + "--data-source-rename=mysql_com_delete:mysql0_cdel", + "--data-source-rename=mysql_com_insert:mysql0_cins", + "--data-source-rename=mysql_com_insert_s:mysql0_cinss", + "--data-source-rename=mysql_com_update:mysql0_cupd", + "--data-source-rename=mysql_com_replace:mysql0_crep", + "--data-source-rename=mysql_com_replace_s:mysql0_creps", + "--data-source-rename=mysql_com_rollback:mysql0_crol", + "--data-source-rename=mysql_aborted_cli:mysql0_acli", + "--data-source-rename=mysql_aborted_conn:mysql0_acon", + "--data-source-rename=mysql_bytes_recv:mysql0_brecv", + "--data-source-rename=mysql_bytes_sent:mysql0_bsent", + "--data-source-rename=mysql_val01:mysql0_val01", + "--data-source-rename=mysql_val02:mysql0_val02", + "--data-source-rename=mysql_val03:mysql0_val03", + "--data-source-rename=mysql_val04:mysql0_val04", + "--data-source-rename=mysql_val05:mysql0_val05", + "--data-source-rename=mysql_val06:mysql0_val06", + "--data-source-rename=mysql_val07:mysql0_val07", + "--data-source-rename=mysql_val08:mysql0_val08", + "--data-source-rename=mysql_val09:mysql0_val09", + "--data-source-rename=mysql_val10:mysql0_val10", + "--data-source-rename=mysql_val11:mysql0_val11", + "--data-source-rename=mysql_val12:mysql0_val12", + "--data-source-rename=mysql_val13:mysql0_val13", + "--data-source-rename=mysql_val14:mysql0_val14", + "--data-source-rename=mysql_val15:mysql0_val15", + ); + + our %mysql_hist = (); + push(@graphs, "mysql_update"); + if($opt_d eq "all" || $debug) { + logger("$myself: Ok"); + } +} + +sub mysql_update { + my $myself = (caller(0))[3]; + my ($debug) = @_; + + my $num; + my $str; + my $n = 0; + my $rrdata = "N"; + + my $print_error = 0; + if($opt_d eq "all" || $debug) { + $print_error = 1; + } + + $MYSQL_CONN_TYPE = $MYSQL_CONN_TYPE || "Host"; + if(lc($MYSQL_CONN_TYPE) eq "host") { + $num = scalar(@MYSQL_HOST_LIST); + } + if(lc($MYSQL_CONN_TYPE) eq "socket") { + $num = scalar(@MYSQL_SOCK_LIST); + } + + for($n = 0; $n < $num; $n++) { + my $host = $MYSQL_HOST_LIST[$n]; + my $port = $MYSQL_PORT_LIST[$n]; + my $user = $MYSQL_USER_LIST[$n]; + my $pass = $MYSQL_PASS_LIST[$n]; + my $sock = $MYSQL_SOCK_LIST[$n]; + my $dbh; + if(lc($MYSQL_CONN_TYPE) eq "host") { + unless ($host && $port && $user && $pass) { + logger("$myself: ERROR: undefined configuration."); + next; + } + $dbh = DBI->connect( + "DBI:mysql:host=$host;port=$port", + $user, + $pass, + { PrintError => $print_error, } + ) or logger("$myself: Cannot connect to MySQL '$host:$port'.") and next; + } + if(lc($MYSQL_CONN_TYPE) eq "socket") { + unless ($sock) { + logger("$myself: ERROR: undefined configuration."); + next; + } + $dbh = DBI->connect( + "DBI:mysql:mysql_socket=$sock", + { PrintError => $print_error, } + ) or logger("$myself: Cannot connect to MySQL '$sock'.") and next; + } + + # SHOW STATUS + my $aborted_clients = 0; + my $aborted_connects = 0; + my $connections = 0; + my $connections_real = 0; + my $innodb_buffer_pool_pages_free = 0; + my $innodb_buffer_pool_pages_total = 0; + my $key_blocks_used = 0; + my $key_blocks_unused = 0; + my $max_used_connections = 0; + my $qcache_free_memory = 0; + my $qcache_hits = 0; + my $qcache_inserts = 0; + my $queries = 0; + my $opened_tables = 0; + my $slow_queries = 0; + my $table_locks_waited = 0; + my $threads_created = 0; + my $sql = "show status"; + my $sth = $dbh->prepare($sql); + $sth->execute; + while((my $name, $value) = $sth->fetchrow_array) { + if($name eq "Aborted_clients") { + $str = $n . "aborted_clients"; + $aborted_clients = $value - $mysql_hist{$str}; + $aborted_clients = 0 unless $aborted_clients != $value; + $aborted_clients /= 60; + $mysql_hist{$str} = $value; + } + if($name eq "Aborted_connects") { + $str = $n . "aborted_connects"; + $aborted_connects = $value - $mysql_hist{$str}; + $aborted_connects = 0 unless $aborted_connects != $value; + $aborted_connects /= 60; + $mysql_hist{$str} = $value; + } + if($name eq "Connections") { + $str = $n . "connections"; + $connections_real = int($value); + $connections = $value - $mysql_hist{$str}; + $connections = 0 unless $connections != $value; + $connections /= 60; + $mysql_hist{$str} = $value; + } + if($name eq "Innodb_buffer_pool_pages_free") { + $innodb_buffer_pool_pages_free = int($value); + } + if($name eq "Innodb_buffer_pool_pages_total") { + $innodb_buffer_pool_pages_total = int($value); + } + if($name eq "Key_blocks_unused") { + $key_blocks_unused = int($value); + } + if($name eq "Key_blocks_used") { + $key_blocks_used = int($value); + } + if($name eq "Max_used_connections") { + $max_used_connections = int($value); + } + if($name eq "Opened_tables") { + $str = $n . "opened_tables"; + $opened_tables = $value - $mysql_hist{$str}; + $opened_tables = 0 unless $opened_tables != $value; + $opened_tables /= 60; + $mysql_hist{$str} = $value; + } + if($name eq "Qcache_free_memory") { + $qcache_free_memory = int($value); + } + if($name eq "Qcache_hits") { + $qcache_hits = int($value); + } + if($name eq "Qcache_inserts") { + $qcache_inserts = int($value); + } + if($name eq "Queries") { + $str = $n . "queries"; + $queries = $value - $mysql_hist{$str}; + $queries = 0 unless $queries != $value; + $queries /= 60; + $mysql_hist{$str} = $value; + } + if($name eq "Slow_queries") { + $str = $n . "slow_queries"; + $slow_queries = $value - $mysql_hist{$str}; + $slow_queries = 0 unless $slow_queries != $value; + $slow_queries /= 60; + $mysql_hist{$str} = $value; + } + if($name eq "Table_locks_waited") { + $str = $n . "table_locks_waited"; + $table_locks_waited = $value - $mysql_hist{$str}; + $table_locks_waited = 0 unless $table_locks_waited != $value; + $table_locks_waited /= 60; + $mysql_hist{$str} = $value; + } + if($name eq "Threads_created") { + $threads_created = int($value); + } + } + $sth->finish; + + # SHOW GLOBAL STATUS + my $bytes_received = 0; + my $bytes_sent = 0; + my $com_commit = 0; + my $com_delete = 0; + my $com_insert = 0; + my $com_insert_s = 0; + my $com_replace = 0; + my $com_replace_s = 0; + my $com_rollback = 0; + my $com_select = 0; + my $com_update = 0; + my $sql = "show global status"; + my $sth = $dbh->prepare($sql); + $sth->execute; + while((my $name, $value) = $sth->fetchrow_array) { + if($name eq "Bytes_received") { + $str = $n . "bytes_received"; + $bytes_received = $value - $mysql_hist{$str}; + $bytes_received = 0 unless $bytes_received != $value; + $bytes_received /= 60; + $mysql_hist{$str} = $value; + } + if($name eq "Bytes_sent") { + $str = $n . "bytes_sent"; + $bytes_sent = $value - $mysql_hist{$str}; + $bytes_sent = 0 unless $bytes_sent != $value; + $bytes_sent /= 60; + $mysql_hist{$str} = $value; + } + if($name eq "Com_commit") { + $str = $n . "com_commit"; + $com_commit = $value - $mysql_hist{$str}; + $com_commit = 0 unless $com_commit != $value; + $com_commit /= 60; + $mysql_hist{$str} = $value; + } + if($name eq "Com_delete") { + $str = $n . "com_delete"; + $com_delete = $value - $mysql_hist{$str}; + $com_delete = 0 unless $com_delete != $value; + $com_delete /= 60; + $mysql_hist{$str} = $value; + } + if($name eq "Com_insert") { + $str = $n . "com_insert"; + $com_insert = $value - $mysql_hist{$str}; + $com_insert = 0 unless $com_insert != $value; + $com_insert /= 60; + $mysql_hist{$str} = $value; + } + if($name eq "Com_insert_select") { + $str = $n . "com_insert_s"; + $com_insert_s = $value - $mysql_hist{$str}; + $com_insert_s = 0 unless $com_insert_s != $value; + $com_insert_s /= 60; + $mysql_hist{$str} = $value; + } + if($name eq "Com_replace") { + $str = $n . "com_replace"; + $com_replace = $value - $mysql_hist{$str}; + $com_replace = 0 unless $com_replace != $value; + $com_replace /= 60; + $mysql_hist{$str} = $value; + } + if($name eq "Com_replace_select") { + $str = $n . "com_replace_s"; + $com_replace_s = $value - $mysql_hist{$str}; + $com_replace_s = 0 unless $com_replace_s != $value; + $com_replace_s /= 60; + $mysql_hist{$str} = $value; + } + if($name eq "Com_rollback") { + $str = $n . "com_rollback"; + $com_rollback = $value - $mysql_hist{$str}; + $com_rollback = 0 unless $com_rollback != $value; + $com_rollback /= 60; + $mysql_hist{$str} = $value; + } + if($name eq "Com_select") { + $str = $n . "com_select"; + $com_select = $value - $mysql_hist{$str}; + $com_select = 0 unless $com_select != $value; + $com_select /= 60; + $mysql_hist{$str} = $value; + } + if($name eq "Com_update") { + $str = $n . "com_update"; + $com_update = $value - $mysql_hist{$str}; + $com_update = 0 unless $com_update != $value; + $com_update /= 60; + $mysql_hist{$str} = $value; + } + } + $sth->finish; + + # SHOW VARIABLES + my $query_cache_size = 0; + my $max_connections = 0; + my $sql = "show variables"; + my $sth = $dbh->prepare($sql); + $sth->execute; + while((my $name, $value) = $sth->fetchrow_array) { + if($name eq "max_connections") { + $max_connections = int($value); + } + if($name eq "query_cache_size") { + $query_cache_size = int($value); + } + } + $sth->finish; + $dbh->disconnect; + + my $tcache_hit_rate = 0; + my $qcache_usage = 0; + my $connections_usage = 0; + my $key_buffer_usage = 0; + my $innodb_buffer_pool_usage = 0; + + $tcache_hit_rate = (1 - ($threads_created / $connections_real)) * 100 + unless !$connections_real; + $qcache_usage = (1 - ($qcache_free_memory / $query_cache_size)) * 100 + unless !$query_cache_size; + $connections_usage = ($max_used_connections / $max_connections) * 100 + unless !$max_connections; + $key_buffer_usage = ($key_blocks_used / ($key_blocks_used + $key_blocks_unused)) * 100 + unless !($key_blocks_used + $key_blocks_unused); + $innodb_buffer_pool_usage = (1 - ($innodb_buffer_pool_pages_free / $innodb_buffer_pool_pages_total)) * 100 + unless !$innodb_buffer_pool_pages_total; + + $connections_usage = $connections_usage > 100 ? 100 : $connections_usage; + + $rrdata .= ":$queries:$slow_queries:$tcache_hit_rate:$qcache_usage:$opened_tables:$connections_usage:$connections:$table_locks_waited:$key_buffer_usage:$innodb_buffer_pool_usage:$com_select:$com_commit:$com_delete:$com_insert:$com_insert_s:$com_update:$com_replace:$com_replace_s:$com_rollback:$aborted_clients:$aborted_connects:$bytes_received:$bytes_sent:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0"; + } + + RRDs::update($MYSQL_RRD, $rrdata); + if($opt_d eq "all" || $debug) { + logger("$myself: $rrdata"); + } + my $err = RRDs::error; + logger("ERROR: while updating $MYSQL_RRD: $err") if $err; +} + +# SQUID graph +# ---------------------------------------------------------------------------- +sub squid_init { + my $myself = (caller(0))[3]; + + if(!(-e $SQUID_RRD)) { + logger("Creating '$SQUID_RRD' file."); + eval { + RRDs::create($SQUID_RRD, + "--step=60", + "DS:squid_g1_1:GAUGE:120:0:U", + "DS:squid_g1_2:GAUGE:120:0:U", + "DS:squid_g1_3:GAUGE:120:0:U", + "DS:squid_g1_4:GAUGE:120:0:U", + "DS:squid_g1_5:GAUGE:120:0:U", + "DS:squid_g1_6:GAUGE:120:0:U", + "DS:squid_g1_7:GAUGE:120:0:U", + "DS:squid_g1_8:GAUGE:120:0:U", + "DS:squid_g1_9:GAUGE:120:0:U", + "DS:squid_g2_1:GAUGE:120:0:U", + "DS:squid_g2_2:GAUGE:120:0:U", + "DS:squid_g2_3:GAUGE:120:0:U", + "DS:squid_g2_4:GAUGE:120:0:U", + "DS:squid_g2_5:GAUGE:120:0:U", + "DS:squid_g2_6:GAUGE:120:0:U", + "DS:squid_g2_7:GAUGE:120:0:U", + "DS:squid_g2_8:GAUGE:120:0:U", + "DS:squid_g2_9:GAUGE:120:0:U", + "DS:squid_rq_1:GAUGE:120:0:U", + "DS:squid_rq_2:GAUGE:120:0:U", + "DS:squid_rq_3:GAUGE:120:0:U", + "DS:squid_rq_4:GAUGE:120:0:U", + "DS:squid_rq_5:GAUGE:120:0:U", + "DS:squid_rq_6:GAUGE:120:0:U", + "DS:squid_rq_7:GAUGE:120:0:U", + "DS:squid_rq_8:GAUGE:120:0:U", + "DS:squid_rq_9:GAUGE:120:0:U", + "DS:squid_m_1:GAUGE:120:0:U", + "DS:squid_m_2:GAUGE:120:0:U", + "DS:squid_m_3:GAUGE:120:0:U", + "DS:squid_m_4:GAUGE:120:0:U", + "DS:squid_m_5:GAUGE:120:0:U", + "DS:squid_ic_1:GAUGE:120:0:U", + "DS:squid_ic_2:GAUGE:120:0:U", + "DS:squid_ic_3:GAUGE:120:0:U", + "DS:squid_ic_4:GAUGE:120:0:U", + "DS:squid_ic_5:GAUGE:120:0:U", + "DS:squid_io_1:GAUGE:120:0:U", + "DS:squid_io_2:GAUGE:120:0:U", + "DS:squid_io_3:GAUGE:120:0:U", + "DS:squid_io_4:GAUGE:120:0:U", + "DS:squid_io_5:GAUGE:120:0:U", + "DS:squid_s_1:GAUGE:120:0:U", + "DS:squid_s_2:GAUGE:120:0:U", + "DS:squid_s_3:GAUGE:120:0:U", + "DS:squid_s_4:GAUGE:120:0:U", + "DS:squid_s_5:GAUGE:120:0:U", + "DS:squid_tc_1:GAUGE:120:0:U", + "DS:squid_tc_2:GAUGE:120:0:U", + "DS:squid_tc_3:GAUGE:120:0:U", + "DS:squid_ts_1:GAUGE:120:0:U", + "DS:squid_ts_2:GAUGE:120:0:U", + "DS:squid_ts_3:GAUGE:120:0:U", + "RRA:AVERAGE:0.5:1:1440", + "RRA:AVERAGE:0.5:30:336", + "RRA:AVERAGE:0.5:60:744", + "RRA:AVERAGE:0.5:1440:365", + "RRA:MIN:0.5:1:1440", + "RRA:MIN:0.5:30:336", + "RRA:MIN:0.5:60:744", + "RRA:MIN:0.5:1440:365", + "RRA:MAX:0.5:1:1440", + "RRA:MAX:0.5:30:336", + "RRA:MAX:0.5:60:744", + "RRA:MAX:0.5:1440:365", + "RRA:LAST:0.5:1:1440", + "RRA:LAST:0.5:30:336", + "RRA:LAST:0.5:60:744", + "RRA:LAST:0.5:1440:365", + ); + }; + my $err = RRDs::error; + if($@ || $err) { + logger("$@") unless !$@; + if($err) { + logger("ERROR: while creating $SQUID_RRD: $err"); + if($err eq "RRDs::error") { + logger("... is the RRDtool Perl package installed?"); + } + } + return; + } + } + + our %squid_hist = (); + push(@graphs, "squid_update"); + if($opt_d eq "all" || $debug) { + logger("$myself: Ok"); + } +} + +sub squid_update { + my $myself = (caller(0))[3]; + my ($debug) = @_; + + my %g12 = (); + my $seek_pos; + my $logsize; + my @data; + my $all; + my $value; + my $g_result; + my $g_status; + + my $rq_client_http_req; + my $rq_client_http_hit; + my $rq_server_http_req; + my $rq_server_ftp_req; + my $rq_server_other_req; + my $rq_aborted_req; + my $rq_swap_files_cleaned; + my $rq_unlink_requests; + + my $tc_client_http_in; + my $tc_client_http_out; + my $ts_server_all_in; + my $ts_server_all_out; + + my $m_alloc; + my $m_inuse; + + my $ic_requests; + my $ic_hits; + my $ic_misses; + + my $io_http; + my $io_ftp; + my $io_gopher; + my $io_wais; + + my $s_entries; + my $s_maximum; + my $s_current; + + my $n; + my $rrdata = "N"; + + $seek_pos = $squid_hist{'seek_pos'}; + $seek_pos = defined($seek_pos) ? int($seek_pos) : 0; + open(IN, $SQUID_LOG); + if(!seek(IN, 0, 2)) { + logger("Couldn't seek to the end ($SQUID_LOG): $!"); + return; + } + $logsize = tell(IN); + if($logsize < $seek_pos) { + $seek_pos = 0; + } + if(!seek(IN, $seek_pos, 0)) { + logger("Couldn't seek to $seek_pos ($SQUID_LOG): $!"); + return; + } + if(defined($squid_hist{'seek_pos'})) { # avoid initial spike + while() { + (undef, undef, undef, $value) = split(' ', $_); + ($g_result, $g_status) = split('/', $value); + $g12{$g_result}++; + $g12{$g_status}++; + } + } + close(IN); + foreach(@SQUID_GRAPH_1) { + $rrdata .= ":"; + $rrdata .= defined($g12{$_}) ? int($g12{$_}) : 0; + } + foreach(@SQUID_GRAPH_2) { + $rrdata .= ":"; + $rrdata .= defined($g12{$_}) ? int($g12{$_}) : 0; + } + $squid_hist{'seek_pos'} = $logsize; + + open(IN, "$SQUID_CMD mgr:counters |"); + while() { + if(/^client_http\.requests = (\d+)$/) { + $rq_client_http_req = $1 - $squid_hist{'rq_client_http_req'}; + $rq_client_http_req = 0 unless $rq_client_http_req != $1; + $rq_client_http_req /= 60; + $squid_hist{'rq_client_http_req'} = $1; + next; + } + if(/^client_http\.hits = (\d+)$/) { + $rq_client_http_hit = $1 - $squid_hist{'rq_client_http_hit'}; + $rq_client_http_hit = 0 unless $rq_client_http_hit != $1; + $rq_client_http_hit /= 60; + $squid_hist{'rq_client_http_hit'} = $1; + next; + } + if(/^client_http\.kbytes_in = (\d+)$/) { + $tc_client_http_in = $1 - $squid_hist{'tc_client_http_in'}; + $tc_client_http_in = 0 unless $tc_client_http_in != $1; + $tc_client_http_in *= 1024; + $tc_client_http_in /= 60; + $squid_hist{'tc_client_http_in'} = $1; + next; + } + if(/^client_http\.kbytes_out = (\d+)$/) { + $tc_client_http_out = $1 - $squid_hist{'tc_client_http_out'}; + $tc_client_http_out = 0 unless $tc_client_http_out != $1; + $tc_client_http_out *= 1024; + $tc_client_http_out /= 60; + $squid_hist{'tc_client_http_out'} = $1; + next; + } + if(/^server\.all\.kbytes_in = (\d+)$/) { + $ts_server_all_in = $1 - $squid_hist{'ts_server_all_in'}; + $ts_server_all_in = 0 unless $ts_server_all_in != $1; + $ts_server_all_in *= 1024; + $ts_server_all_in /= 60; + $squid_hist{'ts_server_all_in'} = $1; + next; + } + if(/^server\.all\.kbytes_out = (\d+)$/) { + $ts_server_all_out = $1 - $squid_hist{'ts_server_all_out'}; + $ts_server_all_out = 0 unless $ts_server_all_out != $1; + $ts_server_all_out *= 1024; + $ts_server_all_out /= 60; + $squid_hist{'ts_server_all_out'} = $1; + next; + } + if(/^server\.http\.requests = (\d+)$/) { + $rq_server_http_req = $1 - $squid_hist{'rq_server_http_req'}; + $rq_server_http_req = 0 unless $rq_server_http_req != $1; + $rq_server_http_req /= 60; + $squid_hist{'rq_server_http_req'} = $1; + next; + } + if(/^server\.ftp\.requests = (\d+)$/) { + $rq_server_ftp_req = $1 - $squid_hist{'rq_server_ftp_req'}; + $rq_server_ftp_req = 0 unless $rq_server_ftp_req != $1; + $rq_server_ftp_req /= 60; + $squid_hist{'rq_server_ftp_req'} = $1; + next; + } + if(/^server\.other\.requests = (\d+)$/) { + $rq_server_other_req = $1 - $squid_hist{'rq_server_other_req'}; + $rq_server_other_req = 0 unless $rq_server_other_req != $1; + $rq_server_other_req /= 60; + $squid_hist{'rq_server_other_req'} = $1; + next; + } + if(/^unlink\.requests = (\d+)$/) { + $rq_unlink_requests = $1 - $squid_hist{'rq_unlink_requests'}; + $rq_unlink_requests = 0 unless $rq_unlink_requests != $1; + $rq_unlink_requests /= 60; + $squid_hist{'rq_unlink_requests'} = $1; + next; + } + if(/^swap\.files_cleaned = (\d+)$/) { + $rq_swap_files_cleaned = $1 - $squid_hist{'rq_swap_files_cleaned'}; + $rq_swap_files_cleaned = 0 unless $rq_swap_files_cleaned != $1; + $rq_swap_files_cleaned /= 60; + $squid_hist{'rq_swap_files_cleaned'} = $1; + next; + } + if(/^aborted_requests = (\d+)$/) { + $rq_aborted_req = $1 - $squid_hist{'rq_aborted_req'}; + $rq_aborted_req = 0 unless $rq_aborted_req != $1; + $rq_aborted_req /= 60; + $squid_hist{'rq_aborted_req'} = $1; + last; + } + } + close(IN); + $rrdata .= ":$rq_client_http_req:$rq_client_http_hit:$rq_server_http_req:$rq_server_ftp_req:$rq_server_other_req:$rq_aborted_req:$rq_swap_files_cleaned:$rq_unlink_requests:0"; + + open(IN, "$SQUID_CMD mgr:mem |"); + while() { + if(/^Total /) { + (undef, undef, $m_alloc, undef, undef, undef, undef, $m_inuse) = split(' ', $_); + chomp($m_alloc); + chomp($m_inuse); + $m_alloc; + $m_inuse; + last; + } + } + close(IN); + $rrdata .= ":$m_alloc:$m_inuse:0:0:0"; + + open(IN, "$SQUID_CMD mgr:ipcache |"); + while() { + if(/^IPcache Requests:\s+(\d+)$/) { + $ic_requests = $1 - $squid_hist{'ic_requests'}; + $ic_requests = 0 unless $ic_requests != $1; + $ic_requests /= 60; + $squid_hist{'ic_requests'} = $1; + next; + } + if(/^IPcache Hits:\s+(\d+)$/) { + $ic_hits = $1 - $squid_hist{'ic_hits'}; + $ic_hits = 0 unless $ic_hits != $1; + $ic_hits /= 60; + $squid_hist{'ic_hits'} = $1; + next; + } + if(/^IPcache Misses:\s+(\d+)$/) { + $ic_misses = $1 - $squid_hist{'ic_misses'}; + $ic_misses = 0 unless $ic_misses != $1; + $ic_misses /= 60; + $squid_hist{'ic_misses'} = $1; + last; + } + } + close(IN); + $rrdata .= ":$ic_requests:$ic_hits:$ic_misses:0:0"; + + open(IN, "$SQUID_CMD mgr:io |"); + @data = ; + close(IN); + $all = join('', @data); + $all =~ s/\n/ /g; + ($value) = ($all =~ m/ HTTP I\/O number of reads.*?(\d+)/g); + chomp($value); + $io_http = $value - $squid_hist{'io_http'}; + $io_http = 0 unless $io_http != $value; + $io_http /= 60; + $squid_hist{'io_http'} = $value; + ($value) = ($all =~ m/ FTP I\/O number of reads.*?(\d+)/g); + chomp($value); + $io_ftp = $value - $squid_hist{'io_ftp'}; + $io_ftp = 0 unless $io_ftp != $value; + $io_ftp /= 60; + $squid_hist{'io_ftp'} = $value; + ($value) = ($all =~ m/ Gopher I\/O number of reads.*?(\d+)/g); + chomp($value); + $io_gopher = $value - $squid_hist{'io_gopher'}; + $io_gopher = 0 unless $io_gopher != $value; + $io_gopher /= 60; + $squid_hist{'io_gopher'} = $value; + ($value) = ($all =~ m/ WAIS I\/O number of reads.*?(\d+)/g); + chomp($value); + $io_wais = $value - $squid_hist{'io_wais'}; + $io_wais = 0 unless $io_wais != $value; + $io_wais /= 60; + $squid_hist{'io_wais'} = $value; + $rrdata .= ":$io_http:$io_ftp:$io_gopher:$io_wais:0"; + + open(IN, "$SQUID_CMD mgr:storedir |"); + while() { + if(/^Store Entries\s+:\s+(\d+)$/) { + $s_entries = $1; + next; + } + if(/^Maximum Swap Size\s+:\s+(\d+)/) { + $s_maximum = $1; + next; + } + if(/^Current Store Swap Size\s*:\s+(\d+)/) { + $s_current = $1; + last; + } + } + close(IN); + $rrdata .= ":$s_entries:$s_maximum:$s_current:0:0"; + $rrdata .= ":$tc_client_http_in:$tc_client_http_out:0"; + $rrdata .= ":$ts_server_all_in:$ts_server_all_out:0"; + RRDs::update($SQUID_RRD, $rrdata); + if($opt_d eq "all" || $debug) { + logger("$myself: $rrdata"); + } + my $err = RRDs::error; + logger("ERROR: while updating $SQUID_RRD: $err") if $err; +} + +# NFSS graph +# ---------------------------------------------------------------------------- +sub nfss_init { + my $myself = (caller(0))[3]; + + if(!(-e $NFSS_RRD)) { + logger("Creating '$NFSS_RRD' file."); + eval { + RRDs::create($NFSS_RRD, + "--step=60", + "DS:nfss_0:COUNTER:120:0:U", + "DS:nfss_1:COUNTER:120:0:U", + "DS:nfss_2:COUNTER:120:0:U", + "DS:nfss_3:COUNTER:120:0:U", + "DS:nfss_4:COUNTER:120:0:U", + "DS:nfss_5:COUNTER:120:0:U", + "DS:nfss_6:COUNTER:120:0:U", + "DS:nfss_7:COUNTER:120:0:U", + "DS:nfss_8:COUNTER:120:0:U", + "DS:nfss_9:COUNTER:120:0:U", + "DS:nfss_10:COUNTER:120:0:U", + "DS:nfss_11:COUNTER:120:0:U", + "DS:nfss_12:COUNTER:120:0:U", + "DS:nfss_13:COUNTER:120:0:U", + "DS:nfss_14:COUNTER:120:0:U", + "DS:nfss_15:COUNTER:120:0:U", + "DS:nfss_16:COUNTER:120:0:U", + "DS:nfss_17:COUNTER:120:0:U", + "DS:nfss_18:COUNTER:120:0:U", + "DS:nfss_19:COUNTER:120:0:U", + "DS:nfss_20:COUNTER:120:0:U", + "DS:nfss_21:COUNTER:120:0:U", + "DS:nfss_22:COUNTER:120:0:U", + "DS:nfss_23:COUNTER:120:0:U", + "DS:nfss_24:COUNTER:120:0:U", + "DS:nfss_25:COUNTER:120:0:U", + "DS:nfss_26:COUNTER:120:0:U", + "DS:nfss_27:COUNTER:120:0:U", + "DS:nfss_28:COUNTER:120:0:U", + "DS:nfss_29:COUNTER:120:0:U", + "DS:nfss_30:COUNTER:120:0:U", + "DS:nfss_31:COUNTER:120:0:U", + "DS:nfss_32:COUNTER:120:0:U", + "DS:nfss_33:COUNTER:120:0:U", + "DS:nfss_34:COUNTER:120:0:U", + "DS:nfss_35:COUNTER:120:0:U", + "DS:nfss_36:COUNTER:120:0:U", + "DS:nfss_37:COUNTER:120:0:U", + "DS:nfss_38:COUNTER:120:0:U", + "DS:nfss_39:COUNTER:120:0:U", + "DS:nfss_40:COUNTER:120:0:U", + "DS:nfss_41:COUNTER:120:0:U", + "DS:nfss_42:COUNTER:120:0:U", + "DS:nfss_43:COUNTER:120:0:U", + "DS:nfss_44:COUNTER:120:0:U", + "DS:nfss_45:COUNTER:120:0:U", + "DS:nfss_46:COUNTER:120:0:U", + "DS:nfss_47:COUNTER:120:0:U", + "DS:nfss_48:COUNTER:120:0:U", + "DS:nfss_49:COUNTER:120:0:U", + "DS:nfss_rc_1:COUNTER:120:0:U", + "DS:nfss_rc_2:COUNTER:120:0:U", + "DS:nfss_rc_3:COUNTER:120:0:U", + "DS:nfss_rc_4:COUNTER:120:0:U", + "DS:nfss_rc_5:COUNTER:120:0:U", + "DS:nfss_fh_1:COUNTER:120:0:U", + "DS:nfss_fh_2:COUNTER:120:0:U", + "DS:nfss_fh_3:COUNTER:120:0:U", + "DS:nfss_fh_4:COUNTER:120:0:U", + "DS:nfss_fh_5:COUNTER:120:0:U", + "DS:nfss_io_1:COUNTER:120:0:U", + "DS:nfss_io_2:COUNTER:120:0:U", + "DS:nfss_io_3:COUNTER:120:0:U", + "DS:nfss_th_0:COUNTER:120:0:U", + "DS:nfss_th_1:COUNTER:120:0:U", + "DS:nfss_th_2:COUNTER:120:0:U", + "DS:nfss_th_3:COUNTER:120:0:U", + "DS:nfss_th_4:COUNTER:120:0:U", + "DS:nfss_th_5:COUNTER:120:0:U", + "DS:nfss_th_6:COUNTER:120:0:U", + "DS:nfss_th_7:COUNTER:120:0:U", + "DS:nfss_th_8:COUNTER:120:0:U", + "DS:nfss_th_9:COUNTER:120:0:U", + "DS:nfss_th_10:COUNTER:120:0:U", + "DS:nfss_net_1:COUNTER:120:0:U", + "DS:nfss_net_2:COUNTER:120:0:U", + "DS:nfss_net_3:COUNTER:120:0:U", + "DS:nfss_net_4:COUNTER:120:0:U", + "DS:nfss_net_5:COUNTER:120:0:U", + "DS:nfss_rpc_1:COUNTER:120:0:U", + "DS:nfss_rpc_2:COUNTER:120:0:U", + "DS:nfss_rpc_3:COUNTER:120:0:U", + "DS:nfss_rpc_4:COUNTER:120:0:U", + "DS:nfss_rpc_5:COUNTER:120:0:U", + "RRA:AVERAGE:0.5:1:1440", + "RRA:AVERAGE:0.5:30:336", + "RRA:AVERAGE:0.5:60:744", + "RRA:AVERAGE:0.5:1440:365", + "RRA:MIN:0.5:1:1440", + "RRA:MIN:0.5:30:336", + "RRA:MIN:0.5:60:744", + "RRA:MIN:0.5:1440:365", + "RRA:MAX:0.5:1:1440", + "RRA:MAX:0.5:30:336", + "RRA:MAX:0.5:60:744", + "RRA:MAX:0.5:1440:365", + "RRA:LAST:0.5:1:1440", + "RRA:LAST:0.5:30:336", + "RRA:LAST:0.5:60:744", + "RRA:LAST:0.5:1440:365", + ); + }; + my $err = RRDs::error; + if($@ || $err) { + logger("$@") unless !$@; + if($err) { + logger("ERROR: while creating $NFSS_RRD: $err"); + if($err eq "RRDs::error") { + logger("... is the RRDtool Perl package installed?"); + } + } + return; + } + } + + push(@graphs, "nfss_update"); + if($opt_d eq "all" || $debug) { + logger("$myself: Ok"); + } +} + +sub nfss_update { + my $myself = (caller(0))[3]; + my ($debug) = @_; + + my @rc; + my @fh; + my @io; + my @th; + my @net; + my @rpc; + my @nfss; + + my $n; + my $rrdata = "N"; + + if($os eq "Linux") { + open(IN, "/proc/net/rpc/nfsd"); + while() { + if(/^rc\s+(\d+)\s+(\d+)\s+(\d+)$/) { + @rc = ($1, $2, $3); + } + if(/^fh\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)$/) { + @fh = ($1, $2, $3, $4, $5); + } + if(/^io\s+(\d+)\s+(\d+)$/) { + @io = ($1, $2); + } + if(/^th /) { + my @tmp = split(' ', $_); + (undef, undef, @th) = @tmp; + } + if(/^net\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)$/) { + @net = ($1, $2, $3, $4); + } + if(/^rpc\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)$/) { + @rpc = ($1, $2, $3, $4, $5); + } + if(/^proc$NFSS_VERSION /) { + my @tmp = split(' ', $_); + (undef, undef, @nfss) = @tmp; + } + } + close(IN); + } elsif($os eq "FreeBSD" || $os eq "OpenBSD") { + # this part must be finished!!!! XXX + } + + for($n = 0; $n < 50; $n++) { + if(!defined($nfss[$n])) { + $nfss[$n] = 0; + } + $rrdata .= ":" . $nfss[$n]; + } + $rrdata .= ":$rc[0]:$rc[1]:$rc[2]:0:0"; + $rrdata .= ":$fh[0]:$fh[1]:$fh[2]:$fh[3]:$fh[4]"; + $rrdata .= ":$io[0]:$io[1]:0"; + for($n = 0; $n < 11; $n++) { + $rrdata .= ":" . int($th[$n]); + } + $rrdata .= ":$net[0]:$net[1]:$net[2]:$net[3]:0"; + $rrdata .= ":$rpc[0]:$rpc[1]:$rpc[2]:$rpc[3]:$rpc[4]"; + RRDs::update($NFSS_RRD, $rrdata); + if($opt_d eq "all" || $debug) { + logger("$myself: $rrdata"); + } + my $err = RRDs::error; + logger("ERROR: while updating $NFSS_RRD: $err") if $err; +} + +# NFSC graph +# ---------------------------------------------------------------------------- +sub nfsc_init { + my $myself = (caller(0))[3]; + + if(!(-e $NFSC_RRD)) { + logger("Creating '$NFSC_RRD' file."); + eval { + RRDs::create($NFSC_RRD, + "--step=60", + "DS:nfsc_0:COUNTER:120:0:U", + "DS:nfsc_1:COUNTER:120:0:U", + "DS:nfsc_2:COUNTER:120:0:U", + "DS:nfsc_3:COUNTER:120:0:U", + "DS:nfsc_4:COUNTER:120:0:U", + "DS:nfsc_5:COUNTER:120:0:U", + "DS:nfsc_6:COUNTER:120:0:U", + "DS:nfsc_7:COUNTER:120:0:U", + "DS:nfsc_8:COUNTER:120:0:U", + "DS:nfsc_9:COUNTER:120:0:U", + "DS:nfsc_10:COUNTER:120:0:U", + "DS:nfsc_11:COUNTER:120:0:U", + "DS:nfsc_12:COUNTER:120:0:U", + "DS:nfsc_13:COUNTER:120:0:U", + "DS:nfsc_14:COUNTER:120:0:U", + "DS:nfsc_15:COUNTER:120:0:U", + "DS:nfsc_16:COUNTER:120:0:U", + "DS:nfsc_17:COUNTER:120:0:U", + "DS:nfsc_18:COUNTER:120:0:U", + "DS:nfsc_19:COUNTER:120:0:U", + "DS:nfsc_20:COUNTER:120:0:U", + "DS:nfsc_21:COUNTER:120:0:U", + "DS:nfsc_22:COUNTER:120:0:U", + "DS:nfsc_23:COUNTER:120:0:U", + "DS:nfsc_24:COUNTER:120:0:U", + "DS:nfsc_25:COUNTER:120:0:U", + "DS:nfsc_26:COUNTER:120:0:U", + "DS:nfsc_27:COUNTER:120:0:U", + "DS:nfsc_28:COUNTER:120:0:U", + "DS:nfsc_29:COUNTER:120:0:U", + "DS:nfsc_30:COUNTER:120:0:U", + "DS:nfsc_31:COUNTER:120:0:U", + "DS:nfsc_32:COUNTER:120:0:U", + "DS:nfsc_33:COUNTER:120:0:U", + "DS:nfsc_34:COUNTER:120:0:U", + "DS:nfsc_35:COUNTER:120:0:U", + "DS:nfsc_36:COUNTER:120:0:U", + "DS:nfsc_37:COUNTER:120:0:U", + "DS:nfsc_38:COUNTER:120:0:U", + "DS:nfsc_39:COUNTER:120:0:U", + "DS:nfsc_40:COUNTER:120:0:U", + "DS:nfsc_41:COUNTER:120:0:U", + "DS:nfsc_42:COUNTER:120:0:U", + "DS:nfsc_43:COUNTER:120:0:U", + "DS:nfsc_44:COUNTER:120:0:U", + "DS:nfsc_45:COUNTER:120:0:U", + "DS:nfsc_46:COUNTER:120:0:U", + "DS:nfsc_47:COUNTER:120:0:U", + "DS:nfsc_48:COUNTER:120:0:U", + "DS:nfsc_49:COUNTER:120:0:U", + "DS:nfsc_rpc_1:COUNTER:120:0:U", + "DS:nfsc_rpc_2:COUNTER:120:0:U", + "DS:nfsc_rpc_3:COUNTER:120:0:U", + "DS:nfsc_rpc_4:COUNTER:120:0:U", + "DS:nfsc_rpc_5:COUNTER:120:0:U", + "RRA:AVERAGE:0.5:1:1440", + "RRA:AVERAGE:0.5:30:336", + "RRA:AVERAGE:0.5:60:744", + "RRA:AVERAGE:0.5:1440:365", + "RRA:MIN:0.5:1:1440", + "RRA:MIN:0.5:30:336", + "RRA:MIN:0.5:60:744", + "RRA:MIN:0.5:1440:365", + "RRA:MAX:0.5:1:1440", + "RRA:MAX:0.5:30:336", + "RRA:MAX:0.5:60:744", + "RRA:MAX:0.5:1440:365", + "RRA:LAST:0.5:1:1440", + "RRA:LAST:0.5:30:336", + "RRA:LAST:0.5:60:744", + "RRA:LAST:0.5:1440:365", + ); + }; + my $err = RRDs::error; + if($@ || $err) { + logger("$@") unless !$@; + if($err) { + logger("ERROR: while creating $NFSC_RRD: $err"); + if($err eq "RRDs::error") { + logger("... is the RRDtool Perl package installed?"); + } + } + return; + } + } + + push(@graphs, "nfsc_update"); + if($opt_d eq "all" || $debug) { + logger("$myself: Ok"); + } +} + +sub nfsc_update { + my $myself = (caller(0))[3]; + my ($debug) = @_; + + my @rpc; + my @nfsc; + + my $n; + my $rrdata = "N"; + + if($os eq "Linux") { + open(IN, "/proc/net/rpc/nfs"); + while() { + if(/^rpc\s+(\d+)\s+(\d+)\s+(\d+)$/) { + @rpc = ($1, $2, $3); + } + if(/^proc$NFSC_VERSION /) { + my @tmp = split(' ', $_); + (undef, undef, @nfsc) = @tmp; + } + } + close(IN); + } elsif($os eq "FreeBSD" || $os eq "OpenBSD") { + # this part must be finished!!!! XXX + } + + for($n = 0; $n < 50; $n++) { + if(!defined($nfsc[$n])) { + $nfsc[$n] = 0; + } + $rrdata .= ":" . $nfsc[$n]; + } + + $rrdata .= ":$rpc[0]:$rpc[1]:$rpc[2]:0:0"; + RRDs::update($NFSC_RRD, $rrdata); + if($opt_d eq "all" || $debug) { + logger("$myself: $rrdata"); + } + my $err = RRDs::error; + logger("ERROR: while updating $NFSC_RRD: $err") if $err; +} + +# BIND graph +# ---------------------------------------------------------------------------- +sub bind_init { + my $myself = (caller(0))[3]; + + my $info; + my @ds; + my @tmp; + my $n; + + if(-e $BIND_RRD) { + $info = RRDs::info($BIND_RRD); + for my $key (keys %$info) { + if(index($key, 'ds[') == 0) { + if(index($key, '.type') != -1) { + push(@ds, substr($key, 3, index($key, ']') - 3)); + } + } + } + if(scalar(@ds) / 135 != scalar(@BIND_URL_LIST)) { + logger("Detected size mismatch between \@BIND_URL_LIST (" . scalar(@BIND_URL_LIST) . ") and $BIND_RRD (" . scalar(@ds) / 135 . "). Resizing it accordingly. All historic data will be lost. Backup file created."); + rename($BIND_RRD, "$BIND_RRD.bak"); + } + } + + if(!(-e $BIND_RRD)) { + logger("Creating '$BIND_RRD' file."); + for($n = 0; $n < scalar(@BIND_URL_LIST); $n++) { + push(@tmp, "DS:bind" . $n . "_totalinq:GAUGE:120:U:U"); + push(@tmp, "DS:bind" . $n . "_inq01:GAUGE:120:U:U"); + push(@tmp, "DS:bind" . $n . "_inq02:GAUGE:120:U:U"); + push(@tmp, "DS:bind" . $n . "_inq03:GAUGE:120:U:U"); + push(@tmp, "DS:bind" . $n . "_inq04:GAUGE:120:U:U"); + push(@tmp, "DS:bind" . $n . "_inq05:GAUGE:120:U:U"); + push(@tmp, "DS:bind" . $n . "_inq06:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_inq07:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_inq08:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_inq09:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_inq10:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_inq11:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_inq12:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_inq13:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_inq14:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_inq15:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_inq16:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_inq17:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_inq18:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_inq19:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_inq20:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ouq01:GAUGE:120:U:U"); + push(@tmp, "DS:bind" . $n . "_ouq02:GAUGE:120:U:U"); + push(@tmp, "DS:bind" . $n . "_ouq03:GAUGE:120:U:U"); + push(@tmp, "DS:bind" . $n . "_ouq04:GAUGE:120:U:U"); + push(@tmp, "DS:bind" . $n . "_ouq05:GAUGE:120:U:U"); + push(@tmp, "DS:bind" . $n . "_ouq06:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ouq07:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ouq08:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ouq09:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ouq10:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ouq11:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ouq12:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ouq13:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ouq14:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ouq15:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ouq16:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ouq17:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ouq18:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ouq19:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ouq20:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ss01:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ss02:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ss03:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ss04:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ss05:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ss06:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ss07:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ss08:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ss09:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ss10:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ss11:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ss12:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ss13:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ss14:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ss15:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ss16:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ss17:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ss18:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ss19:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_ss20:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_rs01:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_rs02:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_rs03:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_rs04:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_rs05:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_rs06:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_rs07:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_rs08:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_rs09:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_rs10:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_rs11:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_rs12:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_rs13:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_rs14:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_rs15:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_rs16:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_rs17:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_rs18:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_rs19:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_rs20:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_crr01:GAUGE:120:U:U"); + push(@tmp, "DS:bind" . $n . "_crr02:GAUGE:120:U:U"); + push(@tmp, "DS:bind" . $n . "_crr03:GAUGE:120:U:U"); + push(@tmp, "DS:bind" . $n . "_crr04:GAUGE:120:U:U"); + push(@tmp, "DS:bind" . $n . "_crr05:GAUGE:120:U:U"); + push(@tmp, "DS:bind" . $n . "_crr06:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_crr07:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_crr08:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_crr09:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_crr10:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_crr11:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_crr12:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_crr13:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_crr14:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_crr15:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_crr16:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_crr17:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_crr18:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_crr19:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_crr20:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_sio01:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_sio02:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_sio03:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_sio04:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_sio05:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_sio06:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_sio07:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_sio08:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_sio09:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_sio10:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_sio11:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_sio12:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_sio13:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_sio14:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_sio15:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_sio16:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_sio17:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_sio18:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_sio19:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_sio20:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_mem_totaluse:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_mem_inuse:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_mem_blksize:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_mem_ctxtsize:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_mem_lost:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_mem_val01:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_mem_val02:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_mem_val03:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_tsk_workthrds:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_tsk_defquantm:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_tsk_tasksrun:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_tsk_val01:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_tsk_val02:GAUGE:120:0:U"); + push(@tmp, "DS:bind" . $n . "_tsk_val03:GAUGE:120:0:U"); + } + eval { + RRDs::create($BIND_RRD, + "--step=60", + @tmp, + "RRA:AVERAGE:0.5:1:1440", + "RRA:AVERAGE:0.5:30:336", + "RRA:AVERAGE:0.5:60:744", + "RRA:AVERAGE:0.5:1440:365", + "RRA:MIN:0.5:1:1440", + "RRA:MIN:0.5:30:336", + "RRA:MIN:0.5:60:744", + "RRA:MIN:0.5:1440:365", + "RRA:MAX:0.5:1:1440", + "RRA:MAX:0.5:30:336", + "RRA:MAX:0.5:60:744", + "RRA:MAX:0.5:1440:365", + "RRA:LAST:0.5:1:1440", + "RRA:LAST:0.5:30:336", + "RRA:LAST:0.5:60:744", + "RRA:LAST:0.5:1440:365", + ); + }; + my $err = RRDs::error; + if($@ || $err) { + logger("$@") unless !$@; + if($err) { + logger("ERROR: while creating $BIND_RRD: $err"); + if($err eq "RRDs::error") { + logger("... is the RRDtool Perl package installed?"); + } + } + return; + } + } + + our %bind_hist = (); + push(@graphs, "bind_update"); + if($opt_d eq "all" || $debug) { + logger("$myself: Ok"); + } +} + +sub bind_update { + my $myself = (caller(0))[3]; + my ($debug) = @_; + + my $totalinq; + my %inq = (); + my %ouq = (); + my %ss = (); + my %rs = (); + my %crr = (); + my $str; + my $n; + my $rrdata = "N"; + + my $e = 0; + foreach(@BIND_URL_LIST) { + my $ua = LWP::UserAgent->new(timeout => 30); + my $response = $ua->request(HTTP::Request->new('GET', $_)); + my $data = XMLin($response->content); + my $value; + + $value = $data->{bind}->{statistics}->{server}->{requests}->{opcode}->{counter}; + $str = $e . "totalinq"; + $totalinq = $value - $bind_hist{$str}; + $totalinq = 0 unless $totalinq != $value; + $totalinq /= 60; + $bind_hist{$str} = $value; + + $value = $data->{bind}->{statistics}->{server}->{'queries-in'}->{rdtype}; + foreach(keys %{$value}) { + $str = $e . "inq_$_"; + $inq{$str} = $value->{$_}->{counter} - $bind_hist{$str}; + $inq{$str} = 0 unless $inq{$str} != $value->{$_}->{counter}; + $inq{$str} /= 60; + $bind_hist{$str} = $value->{$_}->{counter}; + } + + my $views_default = $data->{bind}->{statistics}->{views}->{view}->{_default}; + $value = $views_default->{rdtype}; + foreach(keys %{$value}) { + $str = $e . "ouq_$_"; + $ouq{$str} = $value->{$_}->{counter} - $bind_hist{$str}; + $ouq{$str} = 0 unless $ouq{$str} != $value->{$_}->{counter}; + $ouq{$str} /= 60; + $bind_hist{$str} = $value->{$_}->{counter}; + } + + $value = $data->{bind}->{statistics}->{server}->{nsstat}; + foreach(keys %{$value}) { + $str = $e . "ss_$_"; + $ss{$str} = $value->{$_}->{counter} - $bind_hist{$str}; + $ss{$str} = 0 unless $ss{$str} != $value->{$_}->{counter}; + $ss{$str} /= 60; + $bind_hist{$str} = $value->{$_}->{counter}; + } + + $value = $views_default->{resstat}; + foreach(keys %{$value}) { + $str = $e . "rs_$_"; + $rs{$str} = $value->{$_}->{counter} - $bind_hist{$str}; + $rs{$str} = 0 unless $rs{$str} != $value->{$_}->{counter}; + $rs{$str} /= 60; + $bind_hist{$str} = $value->{$_}->{counter}; + } + + $value = $views_default->{cache}->{rrset}; + foreach(keys %{$value}) { + $str = $e . "crr_$_"; + $crr{$str} = $value->{$_}->{counter}; + } + +# Socket I/O Statistics +# $value = $data->{bind}->{statistics}->{server}->{sockstat}; +# foreach(keys %{$value}) { +# $str = $e . "sio_$_"; +# $sio{$str} = $value->{$_}->{counter} - $bind_hist{$str}; +# $sio{$str} = 0 unless $sio{$str} != $value->{$_}->{counter}; +# $sio{$str} /= 60; +# $bind_hist{$str} = $value->{$_}->{counter}; +# } + + $rrdata .= ":$totalinq"; + my $i = @BIND_IN_QUERIES_LIST[$e]; + for($n = 0; $n < 20; $n++) { + my $j = @$i[$n]; + $str = $e . "inq_$j"; + $rrdata .= ":"; + $rrdata .= defined($inq{$str}) ? $inq{$str} : 0; + } + $i = @BIND_OUT_QUERIES_LIST[$e]; + for($n = 0; $n < 20; $n++) { + my $j = @$i[$n]; + $str = $e . "ouq_$j"; + $rrdata .= ":"; + $rrdata .= defined($ouq{$str}) ? $ouq{$str} : 0; + } + $i = @BIND_SERVER_STATS_LIST[$e]; + for($n = 0; $n < 20; $n++) { + my $j = @$i[$n]; + $str = $e . "ss_$j"; + $rrdata .= ":"; + $rrdata .= defined($ss{$str}) ? $ss{$str} : 0; + } + $i = @BIND_RESOLVER_STATS_LIST[$e]; + for($n = 0; $n < 20; $n++) { + my $j = @$i[$n]; + $str = $e . "rs_$j"; + $rrdata .= ":"; + $rrdata .= defined($rs{$str}) ? $rs{$str} : 0; + } + $i = @BIND_CACHE_RRSETS_LIST[$e]; + for($n = 0; $n < 20; $n++) { + my $j = @$i[$n]; + $str = $e . "crr_$j"; + $rrdata .= ":"; + $rrdata .= defined($crr{$str}) ? $crr{$str} : 0; + } +# $i = @BIND_SOCKET_IO_STATS_LIST[$e]; + for($n = 0; $n < 20; $n++) { + my $j = @$i[$n]; + $str = $e . "sio_$j"; + $rrdata .= ":"; + $rrdata .= defined($sio{$str}) ? $sio{$str} : 0; + } + $value = $data->{bind}->{statistics}->{memory}; + $rrdata .= ":" . $value->{summary}->{TotalUse}; + $rrdata .= ":" . $value->{summary}->{InUse}; + $rrdata .= ":" . $value->{summary}->{BlockSize}; + $rrdata .= ":" . $value->{summary}->{ContextSize}; + $rrdata .= ":" . $value->{summary}->{Lost}; + $rrdata .= ":0:0:0"; + $value = $data->{bind}->{statistics}->{taskmgr}; + $rrdata .= ":" . $value->{'thread-model'}->{'worker-threads'}; + $rrdata .= ":" . $value->{'thread-model'}->{'default-quantum'}; + $rrdata .= ":" . $value->{'thread-model'}->{'tasks-running'}; + $rrdata .= ":0:0:0"; + + $e++; + } + + RRDs::update($BIND_RRD, $rrdata); + if($opt_d eq "all" || $debug) { + logger("$myself: $rrdata"); + } + my $err = RRDs::error; + logger("ERROR: while updating $BIND_RRD: $err") if $err; +} + +# NTP graph +# ---------------------------------------------------------------------------- +sub ntp_init { + my $myself = (caller(0))[3]; + + my $info; + my @ds; + my @tmp; + my $n; + + if(-e $NTP_RRD) { + $info = RRDs::info($NTP_RRD); + for my $key (keys %$info) { + if(index($key, 'ds[') == 0) { + if(index($key, '.type') != -1) { + push(@ds, substr($key, 3, index($key, ']') - 3)); + } + } + } + if(scalar(@ds) / 14 != scalar(@NTP_HOST_LIST)) { + logger("Detected size mismatch between \@NTP_HOST_LIST (" . scalar(@NTP_HOST_LIST) . ") and $NTP_RRD (" . scalar(@ds) / 14 . "). Resizing it accordingly. All historic data will be lost. Backup file created."); + rename($NTP_RRD, "$NTP_RRD.bak"); + } + } + + if(!(-e $NTP_RRD)) { + logger("Creating '$NTP_RRD' file."); + for($n = 0; $n < scalar(@NTP_HOST_LIST); $n++) { + push(@tmp, "DS:ntp" . $n . "_del:GAUGE:120:U:U"); + push(@tmp, "DS:ntp" . $n . "_off:GAUGE:120:U:U"); + push(@tmp, "DS:ntp" . $n . "_jit:GAUGE:120:U:U"); + push(@tmp, "DS:ntp" . $n . "_str:GAUGE:120:0:U"); + push(@tmp, "DS:ntp" . $n . "_c01:GAUGE:120:0:U"); + push(@tmp, "DS:ntp" . $n . "_c02:GAUGE:120:0:U"); + push(@tmp, "DS:ntp" . $n . "_c03:GAUGE:120:0:U"); + push(@tmp, "DS:ntp" . $n . "_c04:GAUGE:120:0:U"); + push(@tmp, "DS:ntp" . $n . "_c05:GAUGE:120:0:U"); + push(@tmp, "DS:ntp" . $n . "_c06:GAUGE:120:0:U"); + push(@tmp, "DS:ntp" . $n . "_c07:GAUGE:120:0:U"); + push(@tmp, "DS:ntp" . $n . "_c08:GAUGE:120:0:U"); + push(@tmp, "DS:ntp" . $n . "_c09:GAUGE:120:0:U"); + push(@tmp, "DS:ntp" . $n . "_c10:GAUGE:120:0:U"); + } + eval { + RRDs::create($NTP_RRD, + "--step=60", + @tmp, + "RRA:AVERAGE:0.5:1:1440", + "RRA:AVERAGE:0.5:30:336", + "RRA:AVERAGE:0.5:60:744", + "RRA:AVERAGE:0.5:1440:365", + "RRA:MIN:0.5:1:1440", + "RRA:MIN:0.5:30:336", + "RRA:MIN:0.5:60:744", + "RRA:MIN:0.5:1440:365", + "RRA:MAX:0.5:1:1440", + "RRA:MAX:0.5:30:336", + "RRA:MAX:0.5:60:744", + "RRA:MAX:0.5:1440:365", + "RRA:LAST:0.5:1:1440", + "RRA:LAST:0.5:30:336", + "RRA:LAST:0.5:60:744", + "RRA:LAST:0.5:1440:365", + ); + }; + my $err = RRDs::error; + if($@ || $err) { + logger("$@") unless !$@; + if($err) { + logger("ERROR: while creating $NTP_RRD: $err"); + if($err eq "RRDs::error") { + logger("... is the RRDtool Perl package installed?"); + } + } + return; + } + } + + push(@graphs, "ntp_update"); + if($opt_d eq "all" || $debug) { + logger("$myself: Ok"); + } +} + +sub ntp_update { + my $myself = (caller(0))[3]; + my ($debug) = @_; + + my @data; + my $del; + my $off; + my $jit; + my $str; + my $cod; + + my $n; + my $rrdata = "N"; + + my $e = 0; + foreach(@NTP_HOST_LIST) { + open(IN, "ntpq -pn $_ |"); + @data = ; + close(IN); + $cod = $str = $del = $off = $jit = 0; + foreach(@data) { + if(/^\*/) { + (undef, $cod, $str, undef, undef, undef, undef, $del, $off, $jit) = split(' ', $_); + $cod =~ s/\.//g; + chomp($jit); + last; + } + } + $del = 0 unless defined($del); + $off = 0 unless defined($off); + $jit = 0 unless defined($jit); + $str = 0 unless defined($str); + $del /= 1000; + $off /= 1000; + $jit /= 1000; + $rrdata .= ":$del:$off:$jit:$str"; + foreach my $i (@NTP_CODE_LIST[$e]) { + for($n = 0; $n < 10; $n++) { + if($cod eq @$i[$n]) { + $rrdata .= ":1"; + } else { + $rrdata .= ":0"; + } + } + } + $e++; + } + + RRDs::update($NTP_RRD, $rrdata); + if($opt_d eq "all" || $debug) { + logger("$myself: $rrdata"); + } + my $err = RRDs::error; + logger("ERROR: while updating $NTP_RRD: $err") if $err; +} + +# FAIL2BAN graph +# ---------------------------------------------------------------------------- +sub fail2ban_init { + my $myself = (caller(0))[3]; + + my $info; + my @ds; + my @tmp; + my $n; + + if(-e $FAIL2BAN_RRD) { + $info = RRDs::info($FAIL2BAN_RRD); + for my $key (keys %$info) { + if(index($key, 'ds[') == 0) { + if(index($key, '.type') != -1) { + push(@ds, substr($key, 3, index($key, ']') - 3)); + } + } + } + if(scalar(@ds) / 9 != scalar(@FAIL2BAN_LIST)) { + logger("Detected size mismatch between \@FAIL2BAN_LIST (" . scalar(@FAIL2BAN_LIST) . ") and $FAIL2BAN_RRD (" . scalar(@ds) / 9 . "). Resizing it accordingly. All historic data will be lost. Backup file created."); + rename($FAIL2BAN_RRD, "$FAIL2BAN_RRD.bak"); + } + } + + if(!(-e $FAIL2BAN_RRD)) { + logger("Creating '$FAIL2BAN_RRD' file."); + for($n = 0; $n < scalar(@FAIL2BAN_LIST); $n++) { + push(@tmp, "DS:fail2ban" . $n . "_j1:GAUGE:120:0:U"); + push(@tmp, "DS:fail2ban" . $n . "_j2:GAUGE:120:0:U"); + push(@tmp, "DS:fail2ban" . $n . "_j3:GAUGE:120:0:U"); + push(@tmp, "DS:fail2ban" . $n . "_j4:GAUGE:120:0:U"); + push(@tmp, "DS:fail2ban" . $n . "_j5:GAUGE:120:0:U"); + push(@tmp, "DS:fail2ban" . $n . "_j6:GAUGE:120:0:U"); + push(@tmp, "DS:fail2ban" . $n . "_j7:GAUGE:120:0:U"); + push(@tmp, "DS:fail2ban" . $n . "_j8:GAUGE:120:0:U"); + push(@tmp, "DS:fail2ban" . $n . "_j9:GAUGE:120:0:U"); + } + eval { + RRDs::create($FAIL2BAN_RRD, + "--step=60", + @tmp, + "RRA:AVERAGE:0.5:1:1440", + "RRA:AVERAGE:0.5:30:336", + "RRA:AVERAGE:0.5:60:744", + "RRA:AVERAGE:0.5:1440:365", + "RRA:MIN:0.5:1:1440", + "RRA:MIN:0.5:30:336", + "RRA:MIN:0.5:60:744", + "RRA:MIN:0.5:1440:365", + "RRA:MAX:0.5:1:1440", + "RRA:MAX:0.5:30:336", + "RRA:MAX:0.5:60:744", + "RRA:MAX:0.5:1440:365", + "RRA:LAST:0.5:1:1440", + "RRA:LAST:0.5:30:336", + "RRA:LAST:0.5:60:744", + "RRA:LAST:0.5:1440:365", + ); + }; + my $err = RRDs::error; + if($@ || $err) { + logger("$@") unless !$@; + if($err) { + logger("ERROR: while creating $FAIL2BAN_RRD: $err"); + if($err eq "RRDs::error") { + logger("... is the RRDtool Perl package installed?"); + } + } + return; + } + } + + our $fail2ban_hist = 0; + push(@graphs, "fail2ban_update"); + if($opt_d eq "all" || $debug) { + logger("$myself: Ok"); + } +} + +sub fail2ban_update { + my $myself = (caller(0))[3]; + my ($debug) = @_; + + my $seek_pos; + my $logsize; + my @jails; + + my $n; + my $str; + my $rrdata = "N"; + + if(! -r $FAIL2BAN_LOG) { + logger("Couldn't find file $FAIL2BAN_LOG: $!"); + return; + } + + $seek_pos = $fail2ban_hist; + $seek_pos = defined($seek_pos) ? int($seek_pos) : 0; + open(IN, $FAIL2BAN_LOG); + if(!seek(IN, 0, 2)) { + logger("Couldn't seek to the end ($FAIL2BAN_LOG): $!"); + return; + } + $logsize = tell(IN); + if($logsize < $seek_pos) { + $seek_pos = 0; + } + if(!seek(IN, $seek_pos, 0)) { + logger("Couldn't seek to $seek_pos ($FAIL2BAN_LOG): $!"); + return; + } + if($fail2ban_hist > 0) { # avoid initial spike + $date = strftime("%Y-%m-%d", localtime); + while() { + if(/^$date/) { + my $e = 0; + while($e < scalar(@FAIL2BAN_LIST)) { + foreach my $i (@FAIL2BAN_LIST[$e]) { + my $e2 = 0; + foreach my $j (@$i) { + ($str = $j) =~ s/\[/\\[/; + $str =~ s/\]/\\]/; + $jails[$e][$e2] = 0 unless defined $jails[$e][$e2]; + if(/ $str Ban /) { + $jails[$e][$e2]++; + } + $e2++; + } + } + $e++; + } + } + } + } + close(IN); + + my $e = 0; + while($e < scalar(@FAIL2BAN_LIST)) { + for($n = 0; $n < 9; $n++) { + $jails[$e][$n] = 0 unless defined $jails[$e][$n]; + $rrdata .= ":" . $jails[$e][$n]; + } + $e++; + } + + $fail2ban_hist = $logsize; + + RRDs::update($FAIL2BAN_RRD, $rrdata); + if($opt_d eq "all" || $debug) { + logger("$myself: $rrdata"); + } + my $err = RRDs::error; + logger("ERROR: while updating $FAIL2BAN_RRD: $err") if $err; +} + +# ICECAST graph +# ---------------------------------------------------------------------------- +sub icecast_init { + my $myself = (caller(0))[3]; + + my $info; + my @ds; + my @tmp; + my $n; + + if(-e $ICECAST_RRD) { + $info = RRDs::info($ICECAST_RRD); + for my $key (keys %$info) { + if(index($key, 'ds[') == 0) { + if(index($key, '.type') != -1) { + push(@ds, substr($key, 3, index($key, ']') - 3)); + } + } + } + if(scalar(@ds) / 36 != scalar(@ICECAST_URL_LIST)) { + logger("Detected size mismatch between \@ICECAST_URL_LIST (" . scalar(@ICECAST_URL_LIST) . ") and $ICECAST_RRD (" . scalar(@ds) / 36 . "). Resizing it accordingly. All historic data will be lost. Backup file created."); + rename($ICECAST_RRD, "$ICECAST_RRD.bak"); + } + } + + if(!(-e $ICECAST_RRD)) { + logger("Creating '$ICECAST_RRD' file."); + for($n = 0; $n < scalar(@ICECAST_URL_LIST); $n++) { + push(@tmp, "DS:icecast" . $n . "_mp0_ls:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp0_br:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp0_v0:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp0_v1:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp1_ls:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp1_br:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp1_v0:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp1_v1:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp2_ls:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp2_br:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp2_v0:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp2_v1:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp3_ls:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp3_br:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp3_v0:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp3_v1:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp4_ls:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp4_br:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp4_v0:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp4_v1:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp5_ls:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp5_br:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp5_v0:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp5_v1:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp6_ls:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp6_br:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp6_v0:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp6_v1:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp7_ls:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp7_br:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp7_v0:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp7_v1:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp8_ls:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp8_br:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp8_v0:GAUGE:120:0:U"); + push(@tmp, "DS:icecast" . $n . "_mp8_v1:GAUGE:120:0:U"); + } + eval { + RRDs::create($ICECAST_RRD, + "--step=60", + @tmp, + "RRA:AVERAGE:0.5:1:1440", + "RRA:AVERAGE:0.5:30:336", + "RRA:AVERAGE:0.5:60:744", + "RRA:AVERAGE:0.5:1440:365", + "RRA:MIN:0.5:1:1440", + "RRA:MIN:0.5:30:336", + "RRA:MIN:0.5:60:744", + "RRA:MIN:0.5:1440:365", + "RRA:MAX:0.5:1:1440", + "RRA:MAX:0.5:30:336", + "RRA:MAX:0.5:60:744", + "RRA:MAX:0.5:1440:365", + "RRA:LAST:0.5:1:1440", + "RRA:LAST:0.5:30:336", + "RRA:LAST:0.5:60:744", + "RRA:LAST:0.5:1440:365", + ); + }; + my $err = RRDs::error; + if($@ || $err) { + logger("$@") unless !$@; + if($err) { + logger("ERROR: while creating $ICECAST_RRD: $err"); + if($err eq "RRDs::error") { + logger("... is the RRDtool Perl package installed?"); + } + } + return; + } + } + + push(@graphs, "icecast_update"); + if($opt_d eq "all" || $debug) { + logger("$myself: Ok"); + } +} + +sub icecast_update { + my $myself = (caller(0))[3]; + my ($debug) = @_; + + my @ls; + my @br; + + my $n; + my $rrdata = "N"; + + my $e = 0; + foreach(@ICECAST_URL_LIST) { + my $ua = LWP::UserAgent->new(timeout => 30); + my $response = $ua->request(HTTP::Request->new('GET', $_)); + my $data = $response->content; + + $data =~ s/\n//g; + undef(@ls); + undef(@br); + foreach my $i (@ICECAST_MP_LIST[$e]) { + foreach(@$i) { + my $m = "Mount Point " . $_; + my ($b) = ($data =~ m/$m.*?Bitrate:<\/td>(\d*?)<\/td><\/tr>/g); + my ($l) = ($data =~ m/$m.*?Current Listeners:<\/td>(\d*?)<\/td>/g); + $b = 0 unless defined($b); + $l = 0 unless defined($l); + push(@ls, $l); + push(@br, $b); + } + for($n = 0; $n < 9; $n++) { + $ls[$n] = 0 unless defined($ls[$n]); + $br[$n] = 0 unless defined($br[$n]); + $rrdata .= ":" . $ls[$n]; + $rrdata .= ":" . $br[$n]; + $rrdata .= ":" . "0"; + $rrdata .= ":" . "0"; + } + } + $e++; + } + + RRDs::update($ICECAST_RRD, $rrdata); + if($opt_d eq "all" || $debug) { + logger("$myself: $rrdata"); + } + my $err = RRDs::error; + logger("ERROR: while updating $ICECAST_RRD: $err") if $err; +} + +# INT graph +# ---------------------------------------------------------------------------- +sub int_init { + my $myself = (caller(0))[3]; + + if(!(-e $INT_RRD)) { + logger("Creating '$INT_RRD' file."); + eval { + RRDs::create($INT_RRD, + "--step=60", + "DS:int_0:COUNTER:120:0:U", + "DS:int_1:COUNTER:120:0:U", + "DS:int_2:COUNTER:120:0:U", + "DS:int_3:COUNTER:120:0:U", + "DS:int_4:COUNTER:120:0:U", + "DS:int_5:COUNTER:120:0:U", + "DS:int_6:COUNTER:120:0:U", + "DS:int_7:COUNTER:120:0:U", + "DS:int_8:COUNTER:120:0:U", + "DS:int_9:COUNTER:120:0:U", + "DS:int_10:COUNTER:120:0:U", + "DS:int_11:COUNTER:120:0:U", + "DS:int_12:COUNTER:120:0:U", + "DS:int_13:COUNTER:120:0:U", + "DS:int_14:COUNTER:120:0:U", + "DS:int_15:COUNTER:120:0:U", + "DS:int_16:COUNTER:120:0:U", + "DS:int_17:COUNTER:120:0:U", + "DS:int_18:COUNTER:120:0:U", + "DS:int_19:COUNTER:120:0:U", + "DS:int_20:COUNTER:120:0:U", + "DS:int_21:COUNTER:120:0:U", + "DS:int_22:COUNTER:120:0:U", + "DS:int_23:COUNTER:120:0:U", + "DS:int_24:COUNTER:120:0:U", + "DS:int_25:COUNTER:120:0:U", + "DS:int_26:COUNTER:120:0:U", + "DS:int_27:COUNTER:120:0:U", + "DS:int_28:COUNTER:120:0:U", + "DS:int_29:COUNTER:120:0:U", + "DS:int_30:COUNTER:120:0:U", + "DS:int_31:COUNTER:120:0:U", + "DS:int_32:COUNTER:120:0:U", + "DS:int_33:COUNTER:120:0:U", + "DS:int_34:COUNTER:120:0:U", + "DS:int_35:COUNTER:120:0:U", + "DS:int_36:COUNTER:120:0:U", + "DS:int_37:COUNTER:120:0:U", + "DS:int_38:COUNTER:120:0:U", + "DS:int_39:COUNTER:120:0:U", + "DS:int_40:COUNTER:120:0:U", + "DS:int_41:COUNTER:120:0:U", + "DS:int_42:COUNTER:120:0:U", + "DS:int_43:COUNTER:120:0:U", + "DS:int_44:COUNTER:120:0:U", + "DS:int_45:COUNTER:120:0:U", + "DS:int_46:COUNTER:120:0:U", + "DS:int_47:COUNTER:120:0:U", + "DS:int_48:COUNTER:120:0:U", + "DS:int_49:COUNTER:120:0:U", + "DS:int_50:COUNTER:120:0:U", + "DS:int_51:COUNTER:120:0:U", + "DS:int_52:COUNTER:120:0:U", + "DS:int_53:COUNTER:120:0:U", + "DS:int_54:COUNTER:120:0:U", + "DS:int_55:COUNTER:120:0:U", + "DS:int_56:COUNTER:120:0:U", + "DS:int_57:COUNTER:120:0:U", + "DS:int_58:COUNTER:120:0:U", + "DS:int_59:COUNTER:120:0:U", + "DS:int_60:COUNTER:120:0:U", + "DS:int_61:COUNTER:120:0:U", + "DS:int_62:COUNTER:120:0:U", + "DS:int_63:COUNTER:120:0:U", + "DS:int_64:COUNTER:120:0:U", + "DS:int_65:COUNTER:120:0:U", + "DS:int_66:COUNTER:120:0:U", + "DS:int_67:COUNTER:120:0:U", + "DS:int_68:COUNTER:120:0:U", + "DS:int_69:COUNTER:120:0:U", + "DS:int_70:COUNTER:120:0:U", + "DS:int_71:COUNTER:120:0:U", + "DS:int_72:COUNTER:120:0:U", + "DS:int_73:COUNTER:120:0:U", + "DS:int_74:COUNTER:120:0:U", + "DS:int_75:COUNTER:120:0:U", + "DS:int_76:COUNTER:120:0:U", + "DS:int_77:COUNTER:120:0:U", + "DS:int_78:COUNTER:120:0:U", + "DS:int_79:COUNTER:120:0:U", + "DS:int_80:COUNTER:120:0:U", + "DS:int_81:COUNTER:120:0:U", + "DS:int_82:COUNTER:120:0:U", + "DS:int_83:COUNTER:120:0:U", + "DS:int_84:COUNTER:120:0:U", + "DS:int_85:COUNTER:120:0:U", + "DS:int_86:COUNTER:120:0:U", + "DS:int_87:COUNTER:120:0:U", + "DS:int_88:COUNTER:120:0:U", + "DS:int_89:COUNTER:120:0:U", + "DS:int_90:COUNTER:120:0:U", + "DS:int_91:COUNTER:120:0:U", + "DS:int_92:COUNTER:120:0:U", + "DS:int_93:COUNTER:120:0:U", + "DS:int_94:COUNTER:120:0:U", + "DS:int_95:COUNTER:120:0:U", + "DS:int_96:COUNTER:120:0:U", + "DS:int_97:COUNTER:120:0:U", + "DS:int_98:COUNTER:120:0:U", + "DS:int_99:COUNTER:120:0:U", + "DS:int_100:COUNTER:120:0:U", + "DS:int_101:COUNTER:120:0:U", + "DS:int_102:COUNTER:120:0:U", + "DS:int_103:COUNTER:120:0:U", + "DS:int_104:COUNTER:120:0:U", + "DS:int_105:COUNTER:120:0:U", + "DS:int_106:COUNTER:120:0:U", + "DS:int_107:COUNTER:120:0:U", + "DS:int_108:COUNTER:120:0:U", + "DS:int_109:COUNTER:120:0:U", + "DS:int_110:COUNTER:120:0:U", + "DS:int_111:COUNTER:120:0:U", + "DS:int_112:COUNTER:120:0:U", + "DS:int_113:COUNTER:120:0:U", + "DS:int_114:COUNTER:120:0:U", + "DS:int_115:COUNTER:120:0:U", + "DS:int_116:COUNTER:120:0:U", + "DS:int_117:COUNTER:120:0:U", + "DS:int_118:COUNTER:120:0:U", + "DS:int_119:COUNTER:120:0:U", + "DS:int_120:COUNTER:120:0:U", + "DS:int_121:COUNTER:120:0:U", + "DS:int_122:COUNTER:120:0:U", + "DS:int_123:COUNTER:120:0:U", + "DS:int_124:COUNTER:120:0:U", + "DS:int_125:COUNTER:120:0:U", + "DS:int_126:COUNTER:120:0:U", + "DS:int_127:COUNTER:120:0:U", + "DS:int_128:COUNTER:120:0:U", + "DS:int_129:COUNTER:120:0:U", + "DS:int_130:COUNTER:120:0:U", + "DS:int_131:COUNTER:120:0:U", + "DS:int_132:COUNTER:120:0:U", + "DS:int_133:COUNTER:120:0:U", + "DS:int_134:COUNTER:120:0:U", + "DS:int_135:COUNTER:120:0:U", + "DS:int_136:COUNTER:120:0:U", + "DS:int_137:COUNTER:120:0:U", + "DS:int_138:COUNTER:120:0:U", + "DS:int_139:COUNTER:120:0:U", + "DS:int_140:COUNTER:120:0:U", + "DS:int_141:COUNTER:120:0:U", + "DS:int_142:COUNTER:120:0:U", + "DS:int_143:COUNTER:120:0:U", + "DS:int_144:COUNTER:120:0:U", + "DS:int_145:COUNTER:120:0:U", + "DS:int_146:COUNTER:120:0:U", + "DS:int_147:COUNTER:120:0:U", + "DS:int_148:COUNTER:120:0:U", + "DS:int_149:COUNTER:120:0:U", + "DS:int_150:COUNTER:120:0:U", + "DS:int_151:COUNTER:120:0:U", + "DS:int_152:COUNTER:120:0:U", + "DS:int_153:COUNTER:120:0:U", + "DS:int_154:COUNTER:120:0:U", + "DS:int_155:COUNTER:120:0:U", + "DS:int_156:COUNTER:120:0:U", + "DS:int_157:COUNTER:120:0:U", + "DS:int_158:COUNTER:120:0:U", + "DS:int_159:COUNTER:120:0:U", + "DS:int_160:COUNTER:120:0:U", + "DS:int_161:COUNTER:120:0:U", + "DS:int_162:COUNTER:120:0:U", + "DS:int_163:COUNTER:120:0:U", + "DS:int_164:COUNTER:120:0:U", + "DS:int_165:COUNTER:120:0:U", + "DS:int_166:COUNTER:120:0:U", + "DS:int_167:COUNTER:120:0:U", + "DS:int_168:COUNTER:120:0:U", + "DS:int_169:COUNTER:120:0:U", + "DS:int_170:COUNTER:120:0:U", + "DS:int_171:COUNTER:120:0:U", + "DS:int_172:COUNTER:120:0:U", + "DS:int_173:COUNTER:120:0:U", + "DS:int_174:COUNTER:120:0:U", + "DS:int_175:COUNTER:120:0:U", + "DS:int_176:COUNTER:120:0:U", + "DS:int_177:COUNTER:120:0:U", + "DS:int_178:COUNTER:120:0:U", + "DS:int_179:COUNTER:120:0:U", + "DS:int_180:COUNTER:120:0:U", + "DS:int_181:COUNTER:120:0:U", + "DS:int_182:COUNTER:120:0:U", + "DS:int_183:COUNTER:120:0:U", + "DS:int_184:COUNTER:120:0:U", + "DS:int_185:COUNTER:120:0:U", + "DS:int_186:COUNTER:120:0:U", + "DS:int_187:COUNTER:120:0:U", + "DS:int_188:COUNTER:120:0:U", + "DS:int_189:COUNTER:120:0:U", + "DS:int_190:COUNTER:120:0:U", + "DS:int_191:COUNTER:120:0:U", + "DS:int_192:COUNTER:120:0:U", + "DS:int_193:COUNTER:120:0:U", + "DS:int_194:COUNTER:120:0:U", + "DS:int_195:COUNTER:120:0:U", + "DS:int_196:COUNTER:120:0:U", + "DS:int_197:COUNTER:120:0:U", + "DS:int_198:COUNTER:120:0:U", + "DS:int_199:COUNTER:120:0:U", + "DS:int_200:COUNTER:120:0:U", + "DS:int_201:COUNTER:120:0:U", + "DS:int_202:COUNTER:120:0:U", + "DS:int_203:COUNTER:120:0:U", + "DS:int_204:COUNTER:120:0:U", + "DS:int_205:COUNTER:120:0:U", + "DS:int_206:COUNTER:120:0:U", + "DS:int_207:COUNTER:120:0:U", + "DS:int_208:COUNTER:120:0:U", + "DS:int_209:COUNTER:120:0:U", + "DS:int_210:COUNTER:120:0:U", + "DS:int_211:COUNTER:120:0:U", + "DS:int_212:COUNTER:120:0:U", + "DS:int_213:COUNTER:120:0:U", + "DS:int_214:COUNTER:120:0:U", + "DS:int_215:COUNTER:120:0:U", + "DS:int_216:COUNTER:120:0:U", + "DS:int_217:COUNTER:120:0:U", + "DS:int_218:COUNTER:120:0:U", + "DS:int_219:COUNTER:120:0:U", + "DS:int_220:COUNTER:120:0:U", + "DS:int_221:COUNTER:120:0:U", + "DS:int_222:COUNTER:120:0:U", + "DS:int_223:COUNTER:120:0:U", + "DS:int_224:COUNTER:120:0:U", + "DS:int_225:COUNTER:120:0:U", + "DS:int_226:COUNTER:120:0:U", + "DS:int_227:COUNTER:120:0:U", + "DS:int_228:COUNTER:120:0:U", + "DS:int_229:COUNTER:120:0:U", + "DS:int_230:COUNTER:120:0:U", + "DS:int_231:COUNTER:120:0:U", + "DS:int_232:COUNTER:120:0:U", + "DS:int_233:COUNTER:120:0:U", + "DS:int_234:COUNTER:120:0:U", + "DS:int_235:COUNTER:120:0:U", + "DS:int_236:COUNTER:120:0:U", + "DS:int_237:COUNTER:120:0:U", + "DS:int_238:COUNTER:120:0:U", + "DS:int_239:COUNTER:120:0:U", + "DS:int_240:COUNTER:120:0:U", + "DS:int_241:COUNTER:120:0:U", + "DS:int_242:COUNTER:120:0:U", + "DS:int_243:COUNTER:120:0:U", + "DS:int_244:COUNTER:120:0:U", + "DS:int_245:COUNTER:120:0:U", + "DS:int_246:COUNTER:120:0:U", + "DS:int_247:COUNTER:120:0:U", + "DS:int_248:COUNTER:120:0:U", + "DS:int_249:COUNTER:120:0:U", + "DS:int_250:COUNTER:120:0:U", + "DS:int_251:COUNTER:120:0:U", + "DS:int_252:COUNTER:120:0:U", + "DS:int_253:COUNTER:120:0:U", + "DS:int_254:COUNTER:120:0:U", + "DS:int_255:COUNTER:120:0:U", + "RRA:AVERAGE:0.5:1:1440", + "RRA:AVERAGE:0.5:30:336", + "RRA:AVERAGE:0.5:60:744", + "RRA:AVERAGE:0.5:1440:365", + "RRA:MIN:0.5:1:1440", + "RRA:MIN:0.5:30:336", + "RRA:MIN:0.5:60:744", + "RRA:MIN:0.5:1440:365", + "RRA:MAX:0.5:1:1440", + "RRA:MAX:0.5:30:336", + "RRA:MAX:0.5:60:744", + "RRA:MAX:0.5:1440:365", + "RRA:LAST:0.5:1:1440", + "RRA:LAST:0.5:30:336", + "RRA:LAST:0.5:60:744", + "RRA:LAST:0.5:1440:365", + ); + }; + my $err = RRDs::error; + if($@ || $err) { + logger("$@") unless !$@; + if($err) { + logger("ERROR: while creating $INT_RRD: $err"); + if($err eq "RRDs::error") { + logger("... is the RRDtool Perl package installed?"); + } + } + return; + } + } + + push(@graphs, "int_update"); + if($opt_d eq "all" || $debug) { + logger("$myself: Ok"); + } +} + +sub int_update { + my $myself = (caller(0))[3]; + my ($debug) = @_; + + my @int; + + my $n; + my $maxints; + my $rrdata = "N"; + + if($os eq "Linux") { + open(IN, "/proc/stat"); + while() { + if(/^intr/) { + my @tmp = split(' ', $_); + (undef, undef, @int) = @tmp; + last; + } + } + close(IN); + } elsif($os eq "FreeBSD" || $os eq "OpenBSD") { + open(IN, "vmstat -i |"); + my @allfields; + my $num; + my $name; + my $ticks; + $maxints = 0; + while() { + if(/^\D{3}\d+/) { + @allfields = split(' ', $_); + $num = $allfields[0]; + $name = $allfields[1]; + $ticks = $allfields[$#allfields - 1]; + chomp($ticks); + if($name eq "timer") { + $num = 0; + } else { + $num =~ s/^\D{3}//; + $num =~ s/://; + } + $int[$num] += $ticks; + $maxints = $maxints < $num ? $num : $maxints; + } + } + close(IN); + for($n = 0; $n < $maxints; $n++) { + $int[$n] = !$int[$n] ? 0 : $int[$n]; + } + } + + for($n = 0; $n < scalar(@int); $n++) { + if(($n % 256) != $n) { + $int[$n % 256] += $int[$n]; + } + } + + for($n = 0; $n < 256; $n++) { + if(!defined($int[$n])) { + $int[$n] = 0; + } + $rrdata .= ":" . $int[$n]; + } + + RRDs::update($INT_RRD, $rrdata); + if($opt_d eq "all" || $debug) { + logger("$myself: $rrdata"); + } + my $err = RRDs::error; + logger("ERROR: while updating $INT_RRD: $err") if $err; +} + +# PC graph +# ---------------------------------------------------------------------------- +sub pc_init { + my $myself = (caller(0))[3]; + + my $info; + my @ds; + my @tmp; + my @data; + my $n; + my $p; + + if(!grep {$_ eq $os} ("Linux")) { + logger("$myself is not supported yet by your operating system ($os)."); + return; + } + + if(-e $PC_RRD) { + $info = RRDs::info($PC_RRD); + for my $key (keys %$info) { + if(index($key, 'ds[') == 0) { + if(index($key, '.type') != -1) { + push(@ds, substr($key, 3, index($key, ']') - 3)); + } + } + } + if(scalar(@ds) / 2 != $PC_MAX) { + logger("Detected size mismatch between \$PC_MAX ($PC_MAX) and $PC_RRD (" . scalar(@ds) / 2 . "). Resizing it accordingly. All historic data will be lost. Backup file created."); + rename($PC_RRD, "$PC_RRD.bak"); + } + } + + if(!(-e $PC_RRD)) { + logger("Creating '$PC_RRD' file."); + for($n = 0; $n < $PC_MAX; $n++) { + push(@tmp, "DS:pc" . $n . "_in:GAUGE:120:0:U"); + push(@tmp, "DS:pc" . $n . "_out:GAUGE:120:0:U"); + } + eval { + RRDs::create($PC_RRD, + "--step=60", + @tmp, + "RRA:AVERAGE:0.5:1:1440", + "RRA:AVERAGE:0.5:30:336", + "RRA:AVERAGE:0.5:60:744", + "RRA:AVERAGE:0.5:1440:365", + "RRA:MIN:0.5:1:1440", + "RRA:MIN:0.5:30:336", + "RRA:MIN:0.5:60:744", + "RRA:MIN:0.5:1440:365", + "RRA:MAX:0.5:1:1440", + "RRA:MAX:0.5:30:336", + "RRA:MAX:0.5:60:744", + "RRA:MAX:0.5:1440:365", + "RRA:LAST:0.5:1:1440", + "RRA:LAST:0.5:30:336", + "RRA:LAST:0.5:60:744", + "RRA:LAST:0.5:1440:365", + ); + }; + my $err = RRDs::error; + if($@ || $err) { + logger("$@") unless !$@; + if($err) { + logger("ERROR: while creating $PC_RRD: $err"); + if($err eq "RRDs::error") { + logger("... is the RRDtool Perl package installed?"); + } + } + return; + } + } + + if($os eq "Linux") { + if(!$NET_GATEWAY) { + logger("You must assign a valid ethernet interface in \$NET_GATEWAY"); + return; + } + # remove the changed PC or those that no longer exist (daily) + open(IN, "iptables -nxvL FORWARD | grep _daily |"); + @data = ; + close(IN); + my $rule; + my $num; + my $exist; + foreach my $d (@data) { + $exist = 0; + (undef, undef, $name) = split(' ', $d); + $name =~ s/_daily//; + for($n = 0; $n < $PC_MAX; $n++) { + if($name eq $PC_LIST[$n]) { + $exist = 1; + last; + } + } + if(!$exist) { + logger("removing unused iptables rule: pc=$name"); + $rule = system("iptables -nxvL FORWARD --line-numbers | grep -w $name" . "_daily 2>/dev/null"); + $rule = split(' ', $rule); + system("iptables -D FORWARD $rule"); + system("iptables -F $name" . "_daily"); + system("iptables -X $name" . "_daily"); + } + } + + # set the iptables rules for each defined PC + my $ip; + for($n = 0; $n < $PC_MAX; $n++) { + if($PC_LIST[$n]) { + if(!($ip = $PC_IP[$n])) { + if(!(gethostbyname($PC_LIST[$n]))) { + logger("DNS problem with: ", $PC_LIST[$n]); + } + $ip = inet_ntoa((gethostbyname($PC_LIST[$n]))[4]); + $ip = $ip . "/32"; + } + undef(@data); + open(IN, "iptables -nxvL $PC_LIST[$n]_daily 2>/dev/null |"); + @data = ; + close(IN); + if(!scalar(@data)) { + system("iptables -N $PC_LIST[$n]_daily"); + system("iptables -I FORWARD -j $PC_LIST[$n]_daily"); + system("iptables -A $PC_LIST[$n]_daily -s $ip -d 0/0 -o $NET_GATEWAY"); + system("iptables -A $PC_LIST[$n]_daily -s 0/0 -d $ip -i $NET_GATEWAY"); + } + } + } + } + + # Since 2.5.2 PC_LAN values need to be converted to GAUGE. + for($n = 0; $n < $PC_MAX; $n++) { + RRDs::tune($PC_RRD, + "--data-source-type=pc" . $n . "_in:GAUGE", + "--data-source-type=pc" . $n . "_out:GAUGE", + ); + } + + our @pc_hist_in = (); + our @pc_hist_out = (); + push(@graphs, "pc_update"); + if($opt_d eq "all" || $debug) { + logger("$myself: Ok"); + } +} + +sub pc_update { + my $myself = (caller(0))[3]; + + my @in; + my @out; + + my $n; + my $ip; + my $rrdata = "N"; + + for($n = 0; $n < $PC_MAX; $n++) { + if($PC_LIST[$n]) { + if(!($ip = $PC_IP[$n])) { + if(!(gethostbyname($PC_LIST[$n]))) { + logger("DNS problem with: ", $PC_LIST[$n]); + } + $ip = inet_ntoa((gethostbyname($PC_LIST[$n]))[4]); + } + $ip =~ s/\/\d+//; + open(IN, "iptables -nxvL $PC_LIST[$n]_daily |"); + $in[$n] = 0 unless $in[$n]; + $out[$n] = 0 unless $out[$n]; + while() { + my (undef, $bytes, undef, undef, undef, undef, $source) = split(' ', $_); + if($source =~ /0.0.0.0/) { + $in[$n] = $bytes - $pc_hist_in[$n]; + $in[$n] = 0 unless $in[$n] != $bytes; + $pc_hist_in[$n] = $bytes; + $in[$n] /= 60; + } + if($source eq $ip) { + $out[$n] = $bytes - $pc_hist_out[$n]; + $out[$n] = 0 unless $out[$n] != $bytes; + $pc_hist_out[$n] = $bytes; + $out[$n] /= 60; + } + } + close(IN); + } + } + + for($n = 0; $n < $PC_MAX; $n++) { + $rrdata .= ":$in[$n]:$out[$n]"; + } + + RRDs::update($PC_RRD, $rrdata); + if($opt_d eq "all") { + logger("$myself: $rrdata"); + } + my $err = RRDs::error; + logger("ERROR: while updating $PC_RRD: $err") if $err; +} + +sub get_counters { + my $in; + my $out; + + my $n; + my $ip; + my $day = (localtime(time - 60))[3]; + + for($n = 0; $n < $PC_MAX; $n++) { + if($PC_LIST[$n]) { + if(!($ip = $PC_IP[$n])) { + if(!(gethostbyname($PC_LIST[$n]))) { + logger("DNS problem with: ", $PC_LIST[$n]); + } + $ip = inet_ntoa((gethostbyname($PC_LIST[$n]))[4]); + } + $ip =~ s/\/\d+//; + open(IN, "iptables -nxvL $PC_LIST[$n]_daily |"); + while() { + my (undef, $bytes, undef, undef, undef, undef, $source) = split(' ', $_); + if($source eq $ip) { + $out = $bytes; + } + if($source =~ /0.0.0.0/) { + $in = $bytes; + } + } + close(IN); + if(! -w $USAGE_DIR) { + logger("WARNING: directory '" . $USAGE_DIR ."' doesn't exists or is not writable."); + last; + } else { + open(OUT, ">> " . $USAGE_DIR . $PC_LIST[$n]); + print(OUT "$day $in $out\n"); + close(OUT); + logger("Saved the daily traffic counter for '$PC_LIST[$n]'.") unless !$opt_d; + } + system("iptables -Z $PC_LIST[$n]_daily >/dev/null 2>/dev/null"); + } + } + +} + +sub send_reports { + my $myself = (caller(0))[3]; + my $n; + my $to; + + if(! -x $REPORT_DIR . "send_reports") { + logger("$myself: unable to find the script '" . $REPORT_DIR . "send_reports" . "'."); + return; + } + logger("Sending monthly traffic reports."); + for($n = 0; $n < $PC_MAX; $n++) { + if($PC_LIST[$n]) { + $to = $PC_REPORT_MAIL[$n]; + $to = $PC_DEFAULT_MAIL unless $PC_REPORT_MAIL[$n]; + logger("$myself: $PC_LIST[$n] -> $to [$PC_REPORT_LANG]"); + system("cd $REPORT_DIR ; " . $REPORT_DIR . "send_reports -h $PC_LIST[$n] -c $opt_c &"); + } + } +} + + +# Main +# ---------------------------------------------------------------------------- +getopts("d:vc:p:") || usage(); + +if($opt_v) { + print("Monitorix version " . VERSION . " (" . RELDATE . ")\n"); + print("by Jordi Sanfeliu \n"); + print("http://www.monitorix.org/\n\n"); + exit(0); +} +if(!$opt_c) { + usage(); + exit(1); +} +$opt_c = abs_path($opt_c) unless $^V lt 5.6.2; +if(!stat($opt_c)) { + die("can't open file $opt_c.\n"); +} + +# get the current OS and kernel branch and check its support +my $release; +($os, undef, $release) = uname(); +my ($major, $minor) = split('\.', $release); +$kernel_branch = $major . "." . $minor; +if(!grep {$_ eq $os} @suppsys) { + die("FATAL: your operating system ($os) is not supported.\n"); +} + +# check configuration file syntax (and load it) +if(grep {$_ eq $os} ("FreeBSD", "OpenBSD", "NetBSD")) { + $SIG{'CHLD'} = 'DEFAULT'; +} +if(system("perl -wc $opt_c >/dev/null 2>&1")) { + die("FATAL: configuration file '$opt_c' had compilation errors.\n"); +} +require $opt_c; + + +$0 = sprintf("%s %s%s%s%s", + $^V lt 5.6.2 ? monitorix : abs_path($0), + $opt_c ? "-c $opt_c" : "", + $opt_p ? " -p $opt_p" : "", + $opt_d ? " -d $opt_d" : "", + $opt_v ? " -v" : ""); + +daemonize(); +logger("Starting Monitorix version " . VERSION . " (pid $$)."); + +if($opt_p) { + $opt_p = abs_path($opt_p); + open(PIDFILE, "> $opt_p") + || die("could not open $opt_p for writing"); + print(PIDFILE "$$"); + close(PIDFILE); +} + +# change to safety directory +unless(chdir("/tmp")) { + logger("can't chdir to /tmp: $!"); + unless(chdir("/lost+found")) { + die("Can't chdir to /lost+found: $!"); + } +} + +if($opt_d) { + if($opt_d ne "none" && $opt_d ne "all") { + @graphs_debug = split(',', $opt_d); + foreach my $t (@graphs_debug) { + if(!grep {$_ eq $t} (@GRAPH_NAME)) { + die("Invalid debug key '$t'"); + } + } + } + logger("Entering in debug mode."); + logger("Changed process name to '$0'."); +} + +# save the path of the configuration file +open(OUT, "> $BASE_DIR/cgi-bin/monitorix.conf.path"); +print(OUT "$opt_c\n"); +close(OUT); + +# initialize all enabled graphs +logger("Initializing graphs.") unless !$opt_d; +flush_accounting_rules(); + +my $func; +foreach my $g (@GRAPH_NAME) { + if($GRAPH_ENABLE{$g} eq "Y") { + $func = $g . "_init"; + eval {&$func();}; + if($@) { + logger("WARNING: unexpected errors in function $func()"); + } + } +} +if($PC_LAN eq "Y") { + pc_init(); +} + +if(!scalar(@graphs)) { + logger("nothing to do, exiting."); + exit(0); +} + +# create 'index.html' file +logger("Generating the 'index.html' file.") unless !$opt_d; +create_index(); +logger("Ok, done.") unless !$opt_d; + +alarm(1); +while(1) { + sleep(1); +} diff --git a/monitorix.cgi b/monitorix.cgi new file mode 100755 index 0000000..7c5d644 --- /dev/null +++ b/monitorix.cgi @@ -0,0 +1,13765 @@ +#!/usr/bin/env perl +# +# Monitorix - A lightweight system monitoring tool. +# +# Copyright (C) 2005-2012 by Jordi Sanfeliu +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +no strict "vars"; +no warnings "once"; +use CGI qw/:standard/; +use POSIX; +use RRDs; + +# load the path of the configuration file +open(IN, "< monitorix.conf.path"); +my $opt_config = ; +chomp($opt_config); +close(IN); +if(-f $opt_config) { + require $opt_config; +} elsif(-f "/etc/monitorix.conf") { + require "/etc/monitorix.conf"; +} elsif(-f "/usr/local/etc/monitorix.conf") { + require "/usr/local/etc/monitorix.conf"; +} else { + print("Content-Type: text/html\n"); + print("\n"); + print("Monitorix configuration file '$opt_config' not found!\n"); + print("Other possible locations also failed.\n"); + exit(1); +} + +our $URL = $ENV{HTTPS} ? "https://" . $ENV{HTTP_HOST} : "http://" . $ENV{HTTP_HOST}; +if(!($HOSTNAME)) { + $HOSTNAME = $ENV{SERVER_NAME}; + if(!($HOSTNAME)) { # called from the command line + $HOSTNAME = "127.0.0.1"; + $URL = "http://127.0.0.1"; + } +} +$URL .= $BASE_URL . "/"; + +# get the current OS and kernel branch +my ($os, undef, $release) = uname(); +my ($major, $minor) = split('\.', $release); +my $kernel_branch = $major . "." . $minor; + +my $mode = defined(param('mode')) ? param('mode') : ''; +my $graph = param('graph'); +my $when = param('when'); +my $color = param('color'); +my $val = defined(param('val')) ? param('val') : ''; +my $silent = defined(param('silent')) ? param('silent') : ''; +if($mode ne "localhost") { + ($mode, $val) = split(/\./, $mode); +} + +my ($twhen) = ($when =~ m/(hour|day|week|month|year)$/); +(my $nwhen = $when) =~ s/$twhen// unless !$twhen; +$nwhen = 1 unless $nwhen; +$twhen = "day" unless $twhen; +$when = $nwhen . $twhen; + +# toggle this to 1 if you want to maintain old (2.3-) Monitorix with Multihost +if($backwards_compat_old_multihost) { + $when = $twhen; +} + +our ($res, $tc, $tb, $ts); +($res, $tc, $tb, $ts) = (3600, 'h', 24, 1) if $twhen eq "day"; +($res, $tc, $tb, $ts) = (108000, 'd', 7, 1) if $twhen eq "week"; +($res, $tc, $tb, $ts) = (216000, 'd', 30, 1) if $twhen eq "month"; +($res, $tc, $tb, $ts) = (5184000, 'd', 365, 1) if $twhen eq "year"; + +# Default colors (white theme) +our @graph_colors; +our $warning_color = "--color=CANVAS#880000"; +our $bg_color = "#FFFFFF"; +our $fg_color = "#000000"; +our $title_bg_color = "#777777"; +our $title_fg_color = "#CCCC00"; +our $graph_bg_color = "#CCCCCC"; + +if($color) { + if($color eq "black") { + push(@graph_colors, "--color=CANVAS" . $BLACK{canvas}); + push(@graph_colors, "--color=BACK" . $BLACK{back}); + push(@graph_colors, "--color=FONT" . $BLACK{font}); + push(@graph_colors, "--color=MGRID" . $BLACK{mgrid}); + push(@graph_colors, "--color=GRID" . $BLACK{grid}); + push(@graph_colors, "--color=FRAME" . $BLACK{frame}); + push(@graph_colors, "--color=ARROW" . $BLACK{arrow}); + push(@graph_colors, "--color=SHADEA" . $BLACK{shadea}); + push(@graph_colors, "--color=SHADEB" . $BLACK{shadeb}); + push(@graph_colors, "--color=AXIS" . $BLACK{axis}) if defined($BLACK{axis}); + $bg_color = $BLACK{main_bg}; + $fg_color = $BLACK{main_fg}; + $title_bg_color = $BLACK{title_bg}; + $title_fg_color = $BLACK{title_fg}; + $graph_bg_color = $BLACK{graph_bg}; + } +} + +my @VERSION12; +my @VERSION12_small; +if($RRDs::VERSION > 1.2) { + push(@VERSION12, "--slope-mode"); + push(@VERSION12, "--font=LEGEND:7:"); + push(@VERSION12, "--font=TITLE:9:"); + push(@VERSION12, "--font=UNIT:8:"); + if($RRDs::VERSION >= 1.3) { + push(@VERSION12, "--font=DEFAULT:0:Mono"); + } + if($twhen eq "day") { + push(@VERSION12, "--x-grid=HOUR:1:HOUR:6:HOUR:6:0:%R"); + } + push(@VERSION12_small, "--font=TITLE:8:"); + push(@VERSION12_small, "--font=UNIT:7:"); + if($RRDs::VERSION >= 1.3) { + push(@VERSION12_small, "--font=DEFAULT:0:Mono"); + } +} else { + undef(@VERSION12); + undef(@VERSION12_small); +} + +our %rgraphs = reverse %GRAPHS; + +my $u = ""; +if($silent eq "yes" || $silent eq "imagetag") { + $fg_color = "#000000"; # visible color for text mode + $u = "_"; +} +if($silent eq "imagetagbig") { + $fg_color = "#000000"; # visible color for text mode + $u = ""; +} + +our @nfsv2 = ("null", "getattr", "setattr", "root", "lookup", "readlink", "read", "wrcache", "write", "create", "remove", "rename", "link", "symlink", "mkdir", "rmdir", "readdir", "fsstat"); +our @nfsv3 = ("null", "getattr", "setattr", "lookup", "access", "readlink", "read", "write", "create", "mkdir", "symlink", "mknod", "remove", "rmdir", "rename", "link", "readdir", "readdirplus", "fsstat", "fsinfo", "pathconf", "commit"); +our @nfsv4 = ("null", "read", "write", "commit", "open", "open_conf", "open_noat", "open_dgrd", "close", "setattr", "fsinfo", "renew", "setclntid", "confirm", "lock", "lockt", "locku", "access", "getattr", "lookup", "lookup_root", "remove", "rename", "link", "symlink", "create", "pathconf", "statfs", "readlink", "readdir", "server_caps", "delegreturn", "getacl", "setacl", "fs_locations", "exchange_id", "create_ses", "destroy_ses", "sequence", "get_lease_t", "reclaim_comp", "layoutget", "layoutcommit", "layoutreturn", "getdevlist", "getdevinfo", "ds_write", "ds_commit"); + +sub get_uptime { + my $str; + my $uptime; + + if($os eq "Linux") { + open(IN, "/proc/uptime"); + ($uptime, undef) = split(' ', ); + close(IN); + } elsif($os eq "FreeBSD") { + open(IN, "/sbin/sysctl -n kern.boottime |"); + (undef, undef, undef, $uptime) = split(' ', ); + close(IN); + $uptime =~ s/,//; + $uptime = time - int($uptime); + } elsif($os eq "OpenBSD" || $os eq "NetBSD") { + open(IN, "/sbin/sysctl -n kern.boottime |"); + $uptime = ; + close(IN); + chomp($uptime); + $uptime = time - int($uptime); + } + + my ($d, $h, $m); + my ($d_string, $h_string, $m_string); + + $d = int($uptime / (60 * 60 * 24)); + $h = int($uptime / (60 * 60)) % 24; + $m = int($uptime / 60) % 60; + + $d_string = $d ? sprintf("%d days,", $d) : ""; + $h_string = $h ? sprintf("%d", $h) : ""; + $m_string = $h ? sprintf("%sh %dm", $h, $m) : sprintf("%d min", $m); + + return "$d_string $m_string"; +} + +# SYSTEM graph +# ---------------------------------------------------------------------------- +sub system { + my ($myself, $title) = @_; + + my $width; + my $height; + my @riglim; + my @tmp; + my @tmpz; + my $n; + my $err; + + my $PNG1 = $u . $myself . "1." . $when . ".png"; + my $PNG2 = $u . $myself . "2." . $when . ".png"; + my $PNG3 = $u . $myself . "3." . $when . ".png"; + my $PNG1z = $u . $myself . "1z." . $when . ".png"; + my $PNG2z = $u . $myself . "2z." . $when . ".png"; + my $PNG3z = $u . $myself . "3z." . $when . ".png"; + + $title = !$silent ? $title : ""; + + unlink ("$PNG_DIR" . "$PNG1", + "$PNG_DIR" . "$PNG2", + "$PNG_DIR" . "$PNG3"); + if($ENABLE_ZOOM eq "Y") { + unlink ("$PNG_DIR" . "$PNG1z", + "$PNG_DIR" . "$PNG2z", + "$PNG_DIR" . "$PNG3z"); + } + + if($os eq "Linux") { + $MEMORY = `grep -w MemTotal: /proc/meminfo | awk '{print \$2}'`; + chomp($MEMORY); + } elsif(grep {$_ eq $os} ("FreeBSD", "OpenBSD", "NetBSD")) { + $MEMORY = `/sbin/sysctl -n hw.physmem`; # in bytes + chomp($MEMORY); + $MEMORY = int($MEMORY / 1024); # in KB + } + $MEMORY = int($MEMORY / 1024); # in MB + + if($IFACE_MODE eq "text") { + if($title) { + graph_header($title, 2); + print(" \n"); + print(" \n"); + } + my (undef, undef, undef, $data) = RRDs::fetch("$SYSTEM_RRD", + "--start=-$nwhen$twhen", + "AVERAGE", + "-r $res"); + $err = RRDs::error; + print("ERROR: while fetching $SYSTEM_RRD: $err\n") if $err; + print("
\n");
+		print("       CPU load average    Memory usage in MB     Processes\n");
+		print("Time   1min  5min 15min    Used  Cached Buffers   Total   Run\n");
+		print("------------------------------------------------------------- \n");
+		my $line;
+		my @row;
+		my $time;
+		for($n = 0, $time = $tb; $n < ($tb * $ts); $n++) {
+			$line = @$data[$n];
+			my ($load1, $load5, $load15, $nproc, $npslp, $nprun, $mtotl, $buff, $cach, $free) = @$line;
+			$buff /= 1024;
+			$cach /= 1024;
+			$free /= 1024;
+			@row = ($load1, $load5, $load15, $MEMORY - $free, $cach, $buff, $nproc, $nprun);
+			$time = $time - (1 / $ts);
+			printf(" %2d$tc   %4.1f  %4.1f  %4.1f  %6d  %6d  %6d   %5d %5d \n", $time, @row);
+		}
+		print("\n");
+		print(" system uptime: " . get_uptime() . "\n");
+		print("    
\n"); + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; + } + + if($title) { + graph_header($title, 2); + } + if($SYSTEM1_RIGID eq 1) { + push(@riglim, "--upper-limit=$SYSTEM1_LIMIT"); + } else { + if($SYSTEM1_RIGID eq 2) { + push(@riglim, "--upper-limit=$SYSTEM1_LIMIT"); + push(@riglim, "--rigid"); + } + } + my $UPTIME = get_uptime(); + my $UPTIMELINE; + if($RRDs::VERSION > 1.2) { + $UPTIMELINE = "COMMENT:system uptime\\: " . $UPTIME . "\\c"; + } else { + $UPTIMELINE = "COMMENT:system uptime: " . $UPTIME . "\\c"; + } + + if($title) { + print(" \n"); + print(" \n"); + } + push(@tmp, "AREA:load1#4444EE: 1 min average"); + push(@tmp, "GPRINT:load1:LAST: Current\\: %4.2lf"); + push(@tmp, "GPRINT:load1:AVERAGE: Average\\: %4.2lf"); + push(@tmp, "GPRINT:load1:MIN: Min\\: %4.2lf"); + push(@tmp, "GPRINT:load1:MAX: Max\\: %4.2lf\\n"); + push(@tmp, "LINE1:load1#0000EE"); + push(@tmp, "LINE1:load5#EEEE00: 5 min average"); + push(@tmp, "GPRINT:load5:LAST: Current\\: %4.2lf"); + push(@tmp, "GPRINT:load5:AVERAGE: Average\\: %4.2lf"); + push(@tmp, "GPRINT:load5:MIN: Min\\: %4.2lf"); + push(@tmp, "GPRINT:load5:MAX: Max\\: %4.2lf\\n"); + push(@tmp, "LINE1:load15#00EEEE:15 min average"); + push(@tmp, "GPRINT:load15:LAST: Current\\: %4.2lf"); + push(@tmp, "GPRINT:load15:AVERAGE: Average\\: %4.2lf"); + push(@tmp, "GPRINT:load15:MIN: Min\\: %4.2lf"); + push(@tmp, "GPRINT:load15:MAX: Max\\: %4.2lf\\n"); + push(@tmpz, "AREA:load1#4444EE: 1 min average"); + push(@tmpz, "LINE1:load1#0000EE"); + push(@tmpz, "LINE1:load5#EEEE00: 5 min average"); + push(@tmpz, "LINE1:load15#00EEEE:15 min average"); + if($os eq "FreeBSD") { + push(@tmp, "COMMENT: \\n"); + } + ($width, $height) = split('x', $GRAPH_SIZE{main}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG1", + "--title=$rgraphs{_system1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Load average", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:load1=$SYSTEM_RRD:system_load1:AVERAGE", + "DEF:load5=$SYSTEM_RRD:system_load5:AVERAGE", + "DEF:load15=$SYSTEM_RRD:system_load15:AVERAGE", + @tmp, + "COMMENT: \\n", + $UPTIMELINE); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG1: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG1z", + "--title=$rgraphs{_system1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Load average", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:load1=$SYSTEM_RRD:system_load1:AVERAGE", + "DEF:load5=$SYSTEM_RRD:system_load5:AVERAGE", + "DEF:load15=$SYSTEM_RRD:system_load15:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG1z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /system1/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + if($title) { + print(" \n"); + print(" \n"); + } + + undef(@riglim); + if($SYSTEM2_RIGID eq 1) { + push(@riglim, "--upper-limit=$SYSTEM2_LIMIT"); + } else { + if($SYSTEM2_RIGID eq 2) { + push(@riglim, "--upper-limit=$SYSTEM2_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + push(@tmp, "AREA:npslp#44AAEE:Sleeping"); + push(@tmp, "AREA:nprun#EE4444:Running"); + push(@tmp, "LINE1:nprun#EE0000"); + push(@tmp, "LINE1:npslp#00EEEE"); + push(@tmp, "LINE1:nproc#EEEE00:Processes"); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG2", + "--title=$rgraphs{_system2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Processes", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:nproc=$SYSTEM_RRD:system_nproc:AVERAGE", + "DEF:npslp=$SYSTEM_RRD:system_npslp:AVERAGE", + "DEF:nprun=$SYSTEM_RRD:system_nprun:AVERAGE", + @tmp, + "COMMENT: \\n"); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG2: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG2z", + "--title=$rgraphs{_system2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Processes", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:nproc=$SYSTEM_RRD:system_nproc:AVERAGE", + "DEF:npslp=$SYSTEM_RRD:system_npslp:AVERAGE", + "DEF:nprun=$SYSTEM_RRD:system_nprun:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG2z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /system2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@tmp); + undef(@tmpz); + if($os eq "Linux") { + push(@tmp, "AREA:m_mused#EE4444:Used"); + push(@tmp, "AREA:m_mcach#44EE44:Cached"); + push(@tmp, "AREA:m_mbuff#CCCCCC:Buffers"); + push(@tmp, "LINE1:m_mbuff#888888"); + push(@tmp, "LINE1:m_mcach#00EE00"); + push(@tmp, "LINE1:m_mused#EE0000"); + } elsif($os eq "FreeBSD") { + push(@tmp, "AREA:m_mused#EE4444:Used"); + push(@tmp, "AREA:m_mcach#44EE44:Cached"); + push(@tmp, "AREA:m_mbuff#CCCCCC:Buffers"); + push(@tmp, "AREA:m_macti#EEEE44:Active"); + push(@tmp, "AREA:m_minac#4444EE:Inactive"); + push(@tmp, "LINE1:m_minac#0000EE"); + push(@tmp, "LINE1:m_macti#EEEE00"); + push(@tmp, "LINE1:m_mbuff#888888"); + push(@tmp, "LINE1:m_mcach#00EE00"); + push(@tmp, "LINE1:m_mused#EE0000"); + } elsif($os eq "OpenBSD" || $os eq "NetBSD") { + push(@tmp, "AREA:m_mused#EE4444:Used"); + push(@tmp, "AREA:m_macti#44EE44:Active"); + push(@tmp, "LINE1:m_macti#00EE00"); + push(@tmp, "LINE1:m_mused#EE0000"); + } + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG3", + "--title=$rgraphs{_system3} (${MEMORY}MB) ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Megabytes", + "--width=$width", + "--height=$height", + "--upper-limit=$MEMORY", + "--lower-limit=0", + "--base=1024", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:mtotl=$SYSTEM_RRD:system_mtotl:AVERAGE", + "DEF:mbuff=$SYSTEM_RRD:system_mbuff:AVERAGE", + "DEF:mcach=$SYSTEM_RRD:system_mcach:AVERAGE", + "DEF:mfree=$SYSTEM_RRD:system_mfree:AVERAGE", + "DEF:macti=$SYSTEM_RRD:system_macti:AVERAGE", + "DEF:minac=$SYSTEM_RRD:system_minac:AVERAGE", + "CDEF:m_mtotl=mtotl,1024,/", + "CDEF:m_mbuff=mbuff,1024,/", + "CDEF:m_mcach=mcach,1024,/", + "CDEF:m_mused=m_mtotl,mfree,1024,/,-", + "CDEF:m_macti=macti,1024,/", + "CDEF:m_minac=minac,1024,/", + @tmp, + "COMMENT: \\n"); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG3: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG3z", + "--title=$rgraphs{_system3} (${MEMORY}MB) ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Megabytes", + "--width=$width", + "--height=$height", + "--upper-limit=$MEMORY", + "--lower-limit=0", + "--base=1024", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:mtotl=$SYSTEM_RRD:system_mtotl:AVERAGE", + "DEF:mbuff=$SYSTEM_RRD:system_mbuff:AVERAGE", + "DEF:mcach=$SYSTEM_RRD:system_mcach:AVERAGE", + "DEF:mfree=$SYSTEM_RRD:system_mfree:AVERAGE", + "DEF:macti=$SYSTEM_RRD:system_macti:AVERAGE", + "DEF:minac=$SYSTEM_RRD:system_minac:AVERAGE", + "CDEF:m_mtotl=mtotl,1024,/", + "CDEF:m_mbuff=mbuff,1024,/", + "CDEF:m_mcach=mcach,1024,/", + "CDEF:m_mused=m_mtotl,mfree,1024,/,-", + "CDEF:m_macti=macti,1024,/", + "CDEF:m_minac=minac,1024,/", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG3z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /system3/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; +} + +# KERN graph +# ---------------------------------------------------------------------------- +sub kern { + my ($myself, $title) = @_; + + my $width; + my $height; + my @riglim; + my @tmp; + my @tmpz; + my $vlabel; + my $n; + my $err; + + my $PNG1 = $u . $myself . "1." . $when . ".png"; + my $PNG2 = $u . $myself . "2." . $when . ".png"; + my $PNG3 = $u . $myself . "3." . $when . ".png"; + my $PNG1z = $u . $myself . "1z." . $when . ".png"; + my $PNG2z = $u . $myself . "2z." . $when . ".png"; + my $PNG3z = $u . $myself . "3z." . $when . ".png"; + + $title = !$silent ? $title : ""; + + unlink ("$PNG_DIR" . "$PNG1", + "$PNG_DIR" . "$PNG2", + "$PNG_DIR" . "$PNG3"); + if($ENABLE_ZOOM eq "Y") { + unlink ("$PNG_DIR" . "$PNG1z", + "$PNG_DIR" . "$PNG2z", + "$PNG_DIR" . "$PNG3z"); + } + + if($IFACE_MODE eq "text") { + if($title) { + graph_header($title, 2); + print(" \n"); + print(" \n"); + } + my (undef, undef, undef, $data) = RRDs::fetch("$KERN_RRD", + "--start=-$nwhen$twhen", + "AVERAGE", + "-r $res"); + $err = RRDs::error; + print("ERROR: while fetching $KERN_RRD: $err\n") if $err; + print("
\n");
+		print("       Kernel usage                                                                           VFS usage\n");
+		print("Time   User   Nice    Sys   Idle   I/Ow    IRQ   sIRQ  Steal  Guest   Ctxt.Sw  Forks  VForks  dentry   file  inode\n");
+		print("------------------------------------------------------------------------------------------------------------------\n");
+		my $line;
+		my @row;
+		my $time;
+		for($n = 0, $time = $tb; $n < ($tb * $ts); $n++) {
+			$line = @$data[$n];
+			my ($usr, $nic, $sys, $idle, $iow, $irq, $sirq, $steal, $guest, $cs, $dentry, $file, $inode, $forks, $vforks) = @$line;
+			@row = ($usr, $nic, $sys, $idle, $iow, $irq, $sirq, $steal, $guest, $cs, $forks, $vforks, $dentry, $file, $inode);
+			$time = $time - (1 / $ts);
+			printf(" %2d$tc  %4.1f%%  %4.1f%%  %4.1f%%  %4.1f%%  %4.1f%%  %4.1f%%  %4.1f%%  %4.1f%%  %4.1f%%   %7d %6d  %6d   %4.1f%%  %4.1f%%  %4.1f%% \n", $time, @row);
+		}
+		print("    
\n"); + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; + } + + if($title) { + graph_header($title, 2); + } + + if($KERN1_RIGID eq 1) { + push(@riglim, "--upper-limit=$KERN1_LIMIT"); + } else { + if($KERN1_RIGID eq 2) { + push(@riglim, "--upper-limit=$KERN1_LIMIT"); + push(@riglim, "--rigid"); + } + } + if($KERN_GRAPH_MODE eq "R") { + $vlabel = "Percent (%)"; + if($KERN_DATA{user} eq "Y") { + push(@tmp, "AREA:user#4444EE:user"); + push(@tmpz, "AREA:user#4444EE:user"); + push(@tmp, "GPRINT:user:LAST: Current\\: %4.1lf%%"); + push(@tmp, "GPRINT:user:AVERAGE: Average\\: %4.1lf%%"); + push(@tmp, "GPRINT:user:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:user:MAX: Max\\: %4.1lf%%\\n"); + } + if($KERN_DATA{nice} eq "Y") { + push(@tmp, "AREA:nice#EEEE44:nice"); + push(@tmpz, "AREA:nice#EEEE44:nice"); + push(@tmp, "GPRINT:nice:LAST: Current\\: %4.1lf%%"); + push(@tmp, "GPRINT:nice:AVERAGE: Average\\: %4.1lf%%"); + push(@tmp, "GPRINT:nice:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:nice:MAX: Max\\: %4.1lf%%\\n"); + } + if($KERN_DATA{sys} eq "Y") { + push(@tmp, "AREA:sys#44EEEE:system"); + push(@tmpz, "AREA:sys#44EEEE:system"); + push(@tmp, "GPRINT:sys:LAST: Current\\: %4.1lf%%"); + push(@tmp, "GPRINT:sys:AVERAGE: Average\\: %4.1lf%%"); + push(@tmp, "GPRINT:sys:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:sys:MAX: Max\\: %4.1lf%%\\n"); + } + if($KERN_DATA{iow} eq "Y") { + push(@tmp, "AREA:iow#EE44EE:I/O wait"); + push(@tmpz, "AREA:iow#EE44EE:I/O wait"); + push(@tmp, "GPRINT:iow:LAST: Current\\: %4.1lf%%"); + push(@tmp, "GPRINT:iow:AVERAGE: Average\\: %4.1lf%%"); + push(@tmp, "GPRINT:iow:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:iow:MAX: Max\\: %4.1lf%%\\n"); + } + if($os eq "Linux") { + if($KERN_DATA{irq} eq "Y") { + push(@tmp, "AREA:irq#888888:IRQ"); + push(@tmpz, "AREA:irq#888888:IRQ"); + push(@tmp, "GPRINT:irq:LAST: Current\\: %4.1lf%%"); + push(@tmp, "GPRINT:irq:AVERAGE: Average\\: %4.1lf%%"); + push(@tmp, "GPRINT:irq:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:irq:MAX: Max\\: %4.1lf%%\\n"); + } + if($KERN_DATA{sirq} eq "Y") { + push(@tmp, "AREA:sirq#E29136:softIRQ"); + push(@tmpz, "AREA:sirq#E29136:softIRQ"); + push(@tmp, "GPRINT:sirq:LAST: Current\\: %4.1lf%%"); + push(@tmp, "GPRINT:sirq:AVERAGE: Average\\: %4.1lf%%"); + push(@tmp, "GPRINT:sirq:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:sirq:MAX: Max\\: %4.1lf%%\\n"); + } + if($KERN_DATA{steal} eq "Y") { + push(@tmp, "AREA:steal#44EE44:steal"); + push(@tmpz, "AREA:steal#44EE44:steal"); + push(@tmp, "GPRINT:steal:LAST: Current\\: %4.1lf%%"); + push(@tmp, "GPRINT:steal:AVERAGE: Average\\: %4.1lf%%"); + push(@tmp, "GPRINT:steal:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:steal:MAX: Max\\: %4.1lf%%\\n"); + } + if($KERN_DATA{guest} eq "Y") { + push(@tmp, "AREA:guest#448844:guest"); + push(@tmpz, "AREA:guest#448844:guest"); + push(@tmp, "GPRINT:guest:LAST: Current\\: %4.1lf%%"); + push(@tmp, "GPRINT:guest:AVERAGE: Average\\: %4.1lf%%"); + push(@tmp, "GPRINT:guest:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:guest:MAX: Max\\: %4.1lf%%\\n"); + } + push(@tmp, "LINE1:guest#1F881F") unless $KERN_DATA{guest} ne "Y"; + push(@tmpz, "LINE1:guest#1F881F") unless $KERN_DATA{guest} ne "Y"; + push(@tmp, "LINE1:steal#00EE00") unless $KERN_DATA{steal} ne "Y"; + push(@tmpz, "LINE1:steal#00EE00") unless $KERN_DATA{steal} ne "Y"; + push(@tmp, "LINE1:sirq#D86612") unless $KERN_DATA{sirq} ne "Y"; + push(@tmpz, "LINE1:sirq#D86612") unless $KERN_DATA{sirq} ne "Y"; + push(@tmp, "LINE1:irq#CCCCCC") unless $KERN_DATA{irq} ne "Y"; + push(@tmpz, "LINE1:irq#CCCCCC") unless $KERN_DATA{irq} ne "Y"; + } + push(@tmp, "LINE1:iow#EE00EE") unless $KERN_DATA{iow} ne "Y"; + push(@tmpz, "LINE1:iow#EE00EE") unless $KERN_DATA{iow} ne "Y"; + push(@tmp, "LINE1:sys#00EEEE") unless $KERN_DATA{sys} ne "Y"; + push(@tmpz, "LINE1:sys#00EEEE") unless $KERN_DATA{sys} ne "Y"; + push(@tmp, "LINE1:nice#EEEE00") unless $KERN_DATA{nice} ne "Y"; + push(@tmpz, "LINE1:nice#EEEE00") unless $KERN_DATA{nice} ne "Y"; + push(@tmp, "LINE1:user#0000EE") unless $KERN_DATA{user} ne "Y"; + push(@tmpz, "LINE1:user#0000EE") unless $KERN_DATA{user} ne "Y"; + } else { + $vlabel = "Stacked Percent (%)"; + push(@tmp, "CDEF:s_nice=user,nice,+"); + push(@tmpz, "CDEF:s_nice=user,nice,+"); + push(@tmp, "CDEF:s_sys=s_nice,sys,+"); + push(@tmpz, "CDEF:s_sys=s_nice,sys,+"); + push(@tmp, "CDEF:s_iow=s_sys,iow,+"); + push(@tmpz, "CDEF:s_iow=s_sys,iow,+"); + if($os eq "Linux") { + push(@tmp, "CDEF:s_irq=s_iow,irq,+"); + push(@tmpz, "CDEF:s_irq=s_iow,irq,+"); + push(@tmp, "CDEF:s_sirq=s_irq,sirq,+"); + push(@tmpz, "CDEF:s_sirq=s_irq,sirq,+"); + push(@tmp, "CDEF:s_steal=s_sirq,steal,+"); + push(@tmpz, "CDEF:s_steal=s_sirq,steal,+"); + push(@tmp, "CDEF:s_guest=s_steal,guest,+"); + push(@tmpz, "CDEF:s_guest=s_steal,guest,+"); + if($KERN_DATA{guest} eq "Y") { + push(@tmp, "AREA:s_guest#448844:guest"); + push(@tmpz, "AREA:s_guest#448844:guest"); + push(@tmp, "GPRINT:guest:LAST: Current\\: %4.1lf%%"); + push(@tmp, "GPRINT:guest:AVERAGE: Average\\: %4.1lf%%"); + push(@tmp, "GPRINT:guest:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:guest:MAX: Max\\: %4.1lf%%\\n"); + } + if($KERN_DATA{steal} eq "Y") { + push(@tmp, "AREA:s_steal#44EE44:steal"); + push(@tmpz, "AREA:s_steal#44EE44:steal"); + push(@tmp, "GPRINT:steal:LAST: Current\\: %4.1lf%%"); + push(@tmp, "GPRINT:steal:AVERAGE: Average\\: %4.1lf%%"); + push(@tmp, "GPRINT:steal:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:steal:MAX: Max\\: %4.1lf%%\\n"); + } + if($KERN_DATA{sirq} eq "Y") { + push(@tmp, "AREA:s_sirq#E29136:softIRQ"); + push(@tmpz, "AREA:s_sirq#E29136:softIRQ"); + push(@tmp, "GPRINT:sirq:LAST: Current\\: %4.1lf%%"); + push(@tmp, "GPRINT:sirq:AVERAGE: Average\\: %4.1lf%%"); + push(@tmp, "GPRINT:sirq:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:sirq:MAX: Max\\: %4.1lf%%\\n"); + } + if($KERN_DATA{irq} eq "Y") { + push(@tmp, "AREA:s_irq#888888:IRQ"); + push(@tmpz, "AREA:s_irq#888888:IRQ"); + push(@tmp, "GPRINT:irq:LAST: Current\\: %4.1lf%%"); + push(@tmp, "GPRINT:irq:AVERAGE: Average\\: %4.1lf%%"); + push(@tmp, "GPRINT:irq:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:irq:MAX: Max\\: %4.1lf%%\\n"); + } + } + if($KERN_DATA{iow} eq "Y") { + push(@tmp, "AREA:s_iow#EE44EE:I/O wait"); + push(@tmpz, "AREA:s_iow#EE44EE:I/O wait"); + push(@tmp, "GPRINT:iow:LAST: Current\\: %4.1lf%%"); + push(@tmp, "GPRINT:iow:AVERAGE: Average\\: %4.1lf%%"); + push(@tmp, "GPRINT:iow:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:iow:MAX: Max\\: %4.1lf%%\\n"); + } + if($KERN_DATA{sys} eq "Y") { + push(@tmp, "AREA:s_sys#44EEEE:system"); + push(@tmpz, "AREA:s_sys#44EEEE:system"); + push(@tmp, "GPRINT:sys:LAST: Current\\: %4.1lf%%"); + push(@tmp, "GPRINT:sys:AVERAGE: Average\\: %4.1lf%%"); + push(@tmp, "GPRINT:sys:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:sys:MAX: Max\\: %4.1lf%%\\n"); + } + if($KERN_DATA{nice} eq "Y") { + push(@tmp, "AREA:s_nice#EEEE44:nice"); + push(@tmpz, "AREA:s_nice#EEEE44:nice"); + push(@tmp, "GPRINT:nice:LAST: Current\\: %4.1lf%%"); + push(@tmp, "GPRINT:nice:AVERAGE: Average\\: %4.1lf%%"); + push(@tmp, "GPRINT:nice:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:nice:MAX: Max\\: %4.1lf%%\\n"); + } + if($KERN_DATA{user} eq "Y") { + push(@tmp, "AREA:user#4444EE:user"); + push(@tmpz, "AREA:user#4444EE:user"); + push(@tmp, "GPRINT:user:LAST: Current\\: %4.1lf%%"); + push(@tmp, "GPRINT:user:AVERAGE: Average\\: %4.1lf%%"); + push(@tmp, "GPRINT:user:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:user:MAX: Max\\: %4.1lf%%\\n"); + } + if($os eq "Linux") { + push(@tmp, "LINE1:s_guest#1F881F"); + push(@tmpz, "LINE1:s_guest#1F881F"); + push(@tmp, "LINE1:s_steal#00EE00"); + push(@tmpz, "LINE1:s_steal#00EE00"); + push(@tmp, "LINE1:s_sirq#D86612"); + push(@tmpz, "LINE1:s_sirq#D86612"); + push(@tmp, "LINE1:s_irq#CCCCCC"); + push(@tmpz, "LINE1:s_irq#CCCCCC"); + } + push(@tmp, "LINE1:s_iow#EE00EE"); + push(@tmpz, "LINE1:s_iow#EE00EE"); + push(@tmp, "LINE1:s_sys#00EEEE"); + push(@tmpz, "LINE1:s_sys#00EEEE"); + push(@tmp, "LINE1:s_nice#EEEE00"); + push(@tmpz, "LINE1:s_nice#EEEE00"); + push(@tmp, "LINE1:user#0000EE"); + push(@tmpz, "LINE1:user#0000EE"); + } + if(grep {$_ eq $os} ("FreeBSD", "OpenBSD", "NetBSD")) { + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + + if($title) { + print(" \n"); + print(" \n"); + } + ($width, $height) = split('x', $GRAPH_SIZE{main}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG1", + "--title=$rgraphs{_kern1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=$vlabel", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:user=$KERN_RRD:kern_user:AVERAGE", + "DEF:nice=$KERN_RRD:kern_nice:AVERAGE", + "DEF:sys=$KERN_RRD:kern_sys:AVERAGE", + "DEF:iow=$KERN_RRD:kern_iow:AVERAGE", + "DEF:irq=$KERN_RRD:kern_irq:AVERAGE", + "DEF:sirq=$KERN_RRD:kern_sirq:AVERAGE", + "DEF:steal=$KERN_RRD:kern_steal:AVERAGE", + "DEF:guest=$KERN_RRD:kern_guest:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG1: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG1z", + "--title=$rgraphs{_kern1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=$vlabel", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:user=$KERN_RRD:kern_user:AVERAGE", + "DEF:nice=$KERN_RRD:kern_nice:AVERAGE", + "DEF:sys=$KERN_RRD:kern_sys:AVERAGE", + "DEF:iow=$KERN_RRD:kern_iow:AVERAGE", + "DEF:irq=$KERN_RRD:kern_irq:AVERAGE", + "DEF:sirq=$KERN_RRD:kern_sirq:AVERAGE", + "DEF:steal=$KERN_RRD:kern_steal:AVERAGE", + "DEF:guest=$KERN_RRD:kern_guest:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG1z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /kern1/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + if($title) { + print(" \n"); + print(" \n"); + } + + undef(@tmp); + undef(@tmpz); + push(@tmp, "AREA:cs#44AAEE:Context switches"); + push(@tmpz, "AREA:cs#44AAEE:Context switches"); + push(@tmp, "GPRINT:cs:LAST: Current\\: %6.0lf\\n"); + push(@tmp, "AREA:forks#4444EE:Forks"); + push(@tmpz, "AREA:forks#4444EE:Forks"); + push(@tmp, "GPRINT:forks:LAST: Current\\: %6.0lf\\n"); + push(@tmp, "LINE1:cs#00EEEE"); + push(@tmp, "LINE1:forks#0000EE"); + push(@tmpz, "LINE1:cs#00EEEE"); + push(@tmpz, "LINE1:forks#0000EE"); + if($os eq "FreeBSD" || $os eq "OpenBSD") { + push(@tmp, "AREA:vforks#EE4444:VForks"); + push(@tmpz, "AREA:vforks#EE4444:VForks"); + push(@tmp, "GPRINT:vforks:LAST: Current\\: %6.0lf\\n"); + push(@tmp, "LINE1:vforks#EE0000"); + push(@tmpz, "LINE1:vforks#EE0000"); + } + + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG2", + "--title=$rgraphs{_kern2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=CS & forks/s", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:cs=$KERN_RRD:kern_cs:AVERAGE", + "DEF:forks=$KERN_RRD:kern_forks:AVERAGE", + "DEF:vforks=$KERN_RRD:kern_vforks:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG2: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG2z", + "--title=$rgraphs{_kern2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=CS & forks/s", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:cs=$KERN_RRD:kern_cs:AVERAGE", + "DEF:forks=$KERN_RRD:kern_forks:AVERAGE", + "DEF:vforks=$KERN_RRD:kern_vforks:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG2z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /kern2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@tmp); + undef(@tmpz); + push(@tmp, "AREA:inode#4444EE:inode"); + push(@tmpz, "AREA:inode#4444EE:inode"); + push(@tmp, "GPRINT:inode:LAST: Current\\: %4.1lf%%\\n"); + if($os eq "Linux") { + push(@tmp, "AREA:dentry#EEEE44:dentry"); + push(@tmpz, "AREA:dentry#EEEE44:dentry"); + push(@tmp, "GPRINT:dentry:LAST: Current\\: %4.1lf%%\\n"); + } + push(@tmp, "AREA:file#EE44EE:file"); + push(@tmpz, "AREA:file#EE44EE:file"); + push(@tmp, "GPRINT:file:LAST: Current\\: %4.1lf%%\\n"); + push(@tmp, "LINE2:inode#0000EE"); + push(@tmpz, "LINE2:inode#0000EE"); + if($os eq "Linux") { + push(@tmp, "LINE2:dentry#EEEE00"); + push(@tmpz, "LINE2:dentry#EEEE00"); + } + push(@tmp, "LINE2:file#EE00EE"); + push(@tmpz, "LINE2:file#EE00EE"); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG3", + "--title=$rgraphs{_kern3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Percent (%)", + "--width=$width", + "--height=$height", + "--upper-limit=100", + "--lower-limit=0", + "--rigid", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:dentry=$KERN_RRD:kern_dentry:AVERAGE", + "DEF:file=$KERN_RRD:kern_file:AVERAGE", + "DEF:inode=$KERN_RRD:kern_inode:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG3: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG3z", + "--title=$rgraphs{_kern3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Percent (%)", + "--width=$width", + "--height=$height", + "--upper-limit=100", + "--lower-limit=0", + "--rigid", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:dentry=$KERN_RRD:kern_dentry:AVERAGE", + "DEF:file=$KERN_RRD:kern_file:AVERAGE", + "DEF:inode=$KERN_RRD:kern_inode:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG3z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /kern3/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; +} + +# PROC graph +# ---------------------------------------------------------------------------- +sub proc { + my ($myself, $title) = @_; + + my $width; + my $height; + my @riglim; + my @PNG; + my @PNGz; + my @tmp; + my @tmpz; + my $vlabel; + my $ncpu; + my $n; + my $str; + my $err; + + if($os eq "Linux") { + $ncpu = `grep -w processor /proc/cpuinfo | tail -1 | awk '{ print \$3 }'`; + chomp($ncpu); + $ncpu++; + } elsif($os eq "FreeBSD") { + $ncpu = `/sbin/sysctl -n hw.ncpu`; + chomp($ncpu); + } + $ncpu = $ncpu > $PROC_MAX ? $PROC_MAX : $ncpu; + return 0 unless $ncpu > 1; + + if($IFACE_MODE eq "text") { + if($title) { + graph_header($title, 2); + print(" \n"); + print(" \n"); + } + my (undef, undef, undef, $data) = RRDs::fetch("$PROC_RRD", + "--start=-$nwhen$twhen", + "AVERAGE", + "-r $res"); + $err = RRDs::error; + print("ERROR: while fetching $PROC_RRD: $err\n") if $err; + print("
\n");
+		for($n = 0; $n < $ncpu; $n++) {
+			print("       Processor " . sprintf("%3d", $n) . "                                   ");
+		}
+		print("\nTime");
+		for($n = 0; $n < $ncpu; $n++) {
+			print("   User  Nice   Sys  Idle  I/Ow   IRQ  sIRQ Steal Guest");
+		}
+		print(" \n----");
+		for($n = 0; $n < $ncpu; $n++) {
+			print("-------------------------------------------------------");
+		}
+		print(" \n");
+		my $line;
+		my @row;
+		my $time;
+		my $n2;
+		my $from;
+		my $to;
+		for($n = 0, $time = $tb; $n < ($tb * $ts); $n++) {
+			$line = @$data[$n];
+			$time = $time - (1 / $ts);
+			printf(" %2d$tc ", $time);
+			for($n2 = 0; $n2 < $ncpu; $n2++) {
+				$from = $n2 * $ncpu;
+				$to = $from + $ncpu;
+				my ($usr, $nic, $sys, $idle, $iow, $irq, $sirq, $steal, $guest,) = @$line[$from..$to];
+				@row = ($usr, $nic, $sys, $idle, $iow, $irq, $sirq, $steal, $guest);
+				printf(" %4.1f%% %4.1f%% %4.1f%% %4.1f%% %4.1f%% %4.1f%% %4.1f%% %4.1f%% %4.1f%% ", @row);
+			}
+			print("\n");
+		}
+		print("    
\n"); + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; + } + + for($n = 0; $n < $ncpu; $n++) { + $str = $u . $myself . $n . "." . $when . ".png"; + push(@PNG, $str); + unlink("$PNG_DIR" . $str); + if($ENABLE_ZOOM eq "Y") { + $str = $u . $myself . $n . "z." . $when . ".png"; + push(@PNGz, $str); + unlink("$PNG_DIR" . $str); + } + } + + if($PROC_RIGID eq 1) { + push(@riglim, "--upper-limit=$PROC_LIMIT"); + } else { + if($PROC_RIGID eq 2) { + push(@riglim, "--upper-limit=$PROC_LIMIT"); + push(@riglim, "--rigid"); + } + } + $n = 0; + while($n < $ncpu) { + if($title) { + if($n == 0) { + graph_header($title, $PROC_PER_ROW); + } + print(" \n"); + } + for($n2 = 0; $n2 < $PROC_PER_ROW; $n2++) { + last unless $n < $ncpu; + if($title) { + print(" \n"); + } + undef(@tmp); + undef(@tmpz); + if($KERN_GRAPH_MODE eq "R") { + $vlabel = "Percent (%)"; + if($KERN_DATA{user} eq "Y") { + push(@tmp, "AREA:user#4444EE:user"); + push(@tmpz, "AREA:user#4444EE:user"); + if($PROC_DATA eq "Y") { + push(@tmp, "GPRINT:user:LAST: Cur\\: %4.1lf%%"); + push(@tmp, "GPRINT:user:AVERAGE: Avg\\: %4.1lf%%"); + push(@tmp, "GPRINT:user:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:user:MAX: Max\\: %4.1lf%%\\n"); + } + } + if($KERN_DATA{nice} eq "Y") { + push(@tmp, "AREA:nice#EEEE44:nice"); + push(@tmpz, "AREA:nice#EEEE44:nice"); + if($PROC_DATA eq "Y") { + push(@tmp, "GPRINT:nice:LAST: Cur\\: %4.1lf%%"); + push(@tmp, "GPRINT:nice:AVERAGE: Avg\\: %4.1lf%%"); + push(@tmp, "GPRINT:nice:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:nice:MAX: Max\\: %4.1lf%%\\n"); + } + } + if($KERN_DATA{sys} eq "Y") { + push(@tmp, "AREA:sys#44EEEE:system"); + push(@tmpz, "AREA:sys#44EEEE:system"); + if($PROC_DATA eq "Y") { + push(@tmp, "GPRINT:sys:LAST: Cur\\: %4.1lf%%"); + push(@tmp, "GPRINT:sys:AVERAGE: Avg\\: %4.1lf%%"); + push(@tmp, "GPRINT:sys:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:sys:MAX: Max\\: %4.1lf%%\\n"); + } + } + if($KERN_DATA{iow} eq "Y") { + push(@tmp, "AREA:iow#EE44EE:I/O wait"); + push(@tmpz, "AREA:iow#EE44EE:I/O wait"); + if($PROC_DATA eq "Y") { + push(@tmp, "GPRINT:iow:LAST:Cur\\: %4.1lf%%"); + push(@tmp, "GPRINT:iow:AVERAGE: Avg\\: %4.1lf%%"); + push(@tmp, "GPRINT:iow:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:iow:MAX: Max\\: %4.1lf%%\\n"); + } + } + if($KERN_DATA{irq} eq "Y") { + push(@tmp, "AREA:irq#888888:IRQ"); + push(@tmpz, "AREA:irq#888888:IRQ"); + if($PROC_DATA eq "Y") { + push(@tmp, "GPRINT:irq:LAST: Cur\\: %4.1lf%%"); + push(@tmp, "GPRINT:irq:AVERAGE: Avg\\: %4.1lf%%"); + push(@tmp, "GPRINT:irq:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:irq:MAX: Max\\: %4.1lf%%\\n"); + } + } + if($KERN_DATA{sirq} eq "Y") { + push(@tmp, "AREA:sirq#E29136:softIRQ"); + push(@tmpz, "AREA:sirq#E29136:softIRQ"); + if($PROC_DATA eq "Y") { + push(@tmp, "GPRINT:sirq:LAST: Cur\\: %4.1lf%%"); + push(@tmp, "GPRINT:sirq:AVERAGE: Avg\\: %4.1lf%%"); + push(@tmp, "GPRINT:sirq:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:sirq:MAX: Max\\: %4.1lf%%\\n"); + } + } + if($KERN_DATA{steal} eq "Y") { + push(@tmp, "AREA:steal#44EE44:steal"); + push(@tmpz, "AREA:steal#44EE44:steal"); + if($PROC_DATA eq "Y") { + push(@tmp, "GPRINT:steal:LAST: Cur\\: %4.1lf%%"); + push(@tmp, "GPRINT:steal:AVERAGE: Avg\\: %4.1lf%%"); + push(@tmp, "GPRINT:steal:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:steal:MAX: Max\\: %4.1lf%%\\n"); + } + } + if($KERN_DATA{guest} eq "Y") { + push(@tmp, "AREA:guest#448844:guest"); + push(@tmpz, "AREA:guest#448844:guest"); + if($PROC_DATA eq "Y") { + push(@tmp, "GPRINT:guest:LAST: Cur\\: %4.1lf%%"); + push(@tmp, "GPRINT:guest:AVERAGE: Avg\\: %4.1lf%%"); + push(@tmp, "GPRINT:guest:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:guest:MAX: Max\\: %4.1lf%%\\n"); + } + } + push(@tmp, "LINE1:guest#1F881F") unless $KERN_DATA{guest} ne "Y"; + push(@tmpz, "LINE1:guest#1F881F") unless $KERN_DATA{guest} ne "Y"; + push(@tmp, "LINE1:steal#00EE00") unless $KERN_DATA{steal} ne "Y"; + push(@tmpz, "LINE1:steal#00EE00") unless $KERN_DATA{steal} ne "Y"; + push(@tmp, "LINE1:sirq#D86612") unless $KERN_DATA{sirq} ne "Y"; + push(@tmpz, "LINE1:sirq#D86612") unless $KERN_DATA{sirq} ne "Y"; + push(@tmp, "LINE1:irq#CCCCCC") unless $KERN_DATA{irq} ne "Y"; + push(@tmpz, "LINE1:irq#CCCCCC") unless $KERN_DATA{irq} ne "Y"; + push(@tmp, "LINE1:iow#EE00EE") unless $KERN_DATA{iow} ne "Y"; + push(@tmpz, "LINE1:iow#EE00EE") unless $KERN_DATA{iow} ne "Y"; + push(@tmp, "LINE1:sys#00EEEE") unless $KERN_DATA{sys} ne "Y"; + push(@tmpz, "LINE1:sys#00EEEE") unless $KERN_DATA{sys} ne "Y"; + push(@tmp, "LINE1:nice#EEEE00") unless $KERN_DATA{nice} ne "Y"; + push(@tmpz, "LINE1:nice#EEEE00") unless $KERN_DATA{nice} ne "Y"; + push(@tmp, "LINE1:user#0000EE") unless $KERN_DATA{user} ne "Y"; + push(@tmpz, "LINE1:user#0000EE") unless $KERN_DATA{user} ne "Y"; + } else { + $vlabel = "Stacked Percent (%)"; + push(@tmp, "CDEF:s_nice=user,nice,+"); + push(@tmpz, "CDEF:s_nice=user,nice,+"); + push(@tmp, "CDEF:s_sys=s_nice,sys,+"); + push(@tmpz, "CDEF:s_sys=s_nice,sys,+"); + push(@tmp, "CDEF:s_iow=s_sys,iow,+"); + push(@tmpz, "CDEF:s_iow=s_sys,iow,+"); + push(@tmp, "CDEF:s_irq=s_iow,irq,+"); + push(@tmpz, "CDEF:s_irq=s_iow,irq,+"); + push(@tmp, "CDEF:s_sirq=s_irq,sirq,+"); + push(@tmpz, "CDEF:s_sirq=s_irq,sirq,+"); + push(@tmp, "CDEF:s_steal=s_sirq,steal,+"); + push(@tmpz, "CDEF:s_steal=s_sirq,steal,+"); + push(@tmp, "CDEF:s_guest=s_steal,guest,+"); + push(@tmpz, "CDEF:s_guest=s_steal,guest,+"); + if($KERN_DATA{guest} eq "Y") { + push(@tmp, "AREA:s_guest#E29136:guest"); + push(@tmpz, "AREA:s_guest#E29136:guest"); + if($PROC_DATA eq "Y") { + push(@tmp, "GPRINT:guest:LAST: Cur\\: %4.1lf%%"); + push(@tmp, "GPRINT:guest:AVERAGE: Avg\\: %4.1lf%%"); + push(@tmp, "GPRINT:guest:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:guest:MAX: Max\\: %4.1lf%%\\n"); + } + } + if($KERN_DATA{steal} eq "Y") { + push(@tmp, "AREA:s_steal#888888:steal"); + push(@tmpz, "AREA:s_steal#888888:steal"); + if($PROC_DATA eq "Y") { + push(@tmp, "GPRINT:steal:LAST: Cur\\: %4.1lf%%"); + push(@tmp, "GPRINT:steal:AVERAGE: Avg\\: %4.1lf%%"); + push(@tmp, "GPRINT:steal:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:steal:MAX: Max\\: %4.1lf%%\\n"); + } + } + if($KERN_DATA{sirq} eq "Y") { + push(@tmp, "AREA:s_sirq#448844:softIRQ"); + push(@tmpz, "AREA:s_sirq#448844:softIRQ"); + if($PROC_DATA eq "Y") { + push(@tmp, "GPRINT:sirq:LAST: Cur\\: %4.1lf%%"); + push(@tmp, "GPRINT:sirq:AVERAGE: Avg\\: %4.1lf%%"); + push(@tmp, "GPRINT:sirq:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:sirq:MAX: Max\\: %4.1lf%%\\n"); + } + } + if($KERN_DATA{irq} eq "Y") { + push(@tmp, "AREA:s_irq#44EE44:IRQ"); + push(@tmpz, "AREA:s_irq#44EE44:IRQ"); + if($PROC_DATA eq "Y") { + push(@tmp, "GPRINT:irq:LAST: Cur\\: %4.1lf%%"); + push(@tmp, "GPRINT:irq:AVERAGE: Avg\\: %4.1lf%%"); + push(@tmp, "GPRINT:irq:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:irq:MAX: Max\\: %4.1lf%%\\n"); + } + } + if($KERN_DATA{iow} eq "Y") { + push(@tmp, "AREA:s_iow#EE44EE:I/O wait"); + push(@tmpz, "AREA:s_iow#EE44EE:I/O wait"); + if($PROC_DATA eq "Y") { + push(@tmp, "GPRINT:iow:LAST:Cur\\: %4.1lf%%"); + push(@tmp, "GPRINT:iow:AVERAGE: Avg\\: %4.1lf%%"); + push(@tmp, "GPRINT:iow:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:iow:MAX: Max\\: %4.1lf%%\\n"); + } + } + if($KERN_DATA{sys} eq "Y") { + push(@tmp, "AREA:s_sys#44EEEE:system"); + push(@tmpz, "AREA:s_sys#44EEEE:system"); + if($PROC_DATA eq "Y") { + push(@tmp, "GPRINT:sys:LAST: Cur\\: %4.1lf%%"); + push(@tmp, "GPRINT:sys:AVERAGE: Avg\\: %4.1lf%%"); + push(@tmp, "GPRINT:sys:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:sys:MAX: Max\\: %4.1lf%%\\n"); + } + } + if($KERN_DATA{nice} eq "Y") { + push(@tmp, "AREA:s_nice#EEEE44:nice"); + push(@tmpz, "AREA:s_nice#EEEE44:nice"); + if($PROC_DATA eq "Y") { + push(@tmp, "GPRINT:nice:LAST: Cur\\: %4.1lf%%"); + push(@tmp, "GPRINT:nice:AVERAGE: Avg\\: %4.1lf%%"); + push(@tmp, "GPRINT:nice:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:nice:MAX: Max\\: %4.1lf%%\\n"); + } + } + if($KERN_DATA{user} eq "Y") { + push(@tmp, "AREA:user#4444EE:user"); + push(@tmpz, "AREA:user#4444EE:user"); + if($PROC_DATA eq "Y") { + push(@tmp, "GPRINT:user:LAST: Cur\\: %4.1lf%%"); + push(@tmp, "GPRINT:user:AVERAGE: Avg\\: %4.1lf%%"); + push(@tmp, "GPRINT:user:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:user:MAX: Max\\: %4.1lf%%\\n"); + } + } + push(@tmp, "LINE1:s_guest#D86612"); + push(@tmpz, "LINE1:s_guest#D86612"); + push(@tmp, "LINE1:s_steal#CCCCCC"); + push(@tmpz, "LINE1:s_steal#CCCCCC"); + push(@tmp, "LINE1:s_sirq#1F881F"); + push(@tmpz, "LINE1:s_sirq#1F881F"); + push(@tmp, "LINE1:s_irq#00EE00"); + push(@tmpz, "LINE1:s_irq#00EE00"); + push(@tmp, "LINE1:s_iow#EE00EE"); + push(@tmpz, "LINE1:s_iow#EE00EE"); + push(@tmp, "LINE1:s_sys#00EEEE"); + push(@tmpz, "LINE1:s_sys#00EEEE"); + push(@tmp, "LINE1:s_nice#EEEE00"); + push(@tmpz, "LINE1:s_nice#EEEE00"); + push(@tmp, "LINE1:user#0000EE"); + push(@tmpz, "LINE1:user#0000EE"); + } + ($width, $height) = split('x', $GRAPH_SIZE{$PROC_SIZE}); + RRDs::graph("$PNG_DIR" . "$PNG[$n]", + "--title=$rgraphs{_proc} $n ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=$vlabel", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:user=$PROC_RRD:proc" . $n . "_user:AVERAGE", + "DEF:nice=$PROC_RRD:proc" . $n . "_nice:AVERAGE", + "DEF:sys=$PROC_RRD:proc" . $n . "_sys:AVERAGE", + "DEF:iow=$PROC_RRD:proc" . $n . "_iow:AVERAGE", + "DEF:irq=$PROC_RRD:proc" . $n . "_irq:AVERAGE", + "DEF:sirq=$PROC_RRD:proc" . $n . "_sirq:AVERAGE", + "DEF:steal=$PROC_RRD:proc" . $n . "_steal:AVERAGE", + "DEF:guest=$PROC_RRD:proc" . $n . "_guest:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG[$n]: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNGz[$n]", + "--title=$rgraphs{_proc} $n ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=$vlabel", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:user=$PROC_RRD:proc" . $n . "_user:AVERAGE", + "DEF:nice=$PROC_RRD:proc" . $n . "_nice:AVERAGE", + "DEF:sys=$PROC_RRD:proc" . $n . "_sys:AVERAGE", + "DEF:iow=$PROC_RRD:proc" . $n . "_iow:AVERAGE", + "DEF:irq=$PROC_RRD:proc" . $n . "_irq:AVERAGE", + "DEF:sirq=$PROC_RRD:proc" . $n . "_sirq:AVERAGE", + "DEF:steal=$PROC_RRD:proc" . $n . "_steal:AVERAGE", + "DEF:guest=$PROC_RRD:proc" . $n . "_guest:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNGz[$n]: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /proc$n/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + if($title) { + print(" \n"); + } + $n++; + } + if($title) { + print(" \n"); + } + } + if($title) { + graph_footer(); + } + return 1; +} + +# HPTEMP graph +# ---------------------------------------------------------------------------- +sub hptemp { + my ($myself, $title) = @_; + + my $width; + my $height; + my @tmp; + my @tmpz; + my $n; + my $id; + my $str; + my $err; + my @LC = ( + "#FFA500", + "#44EEEE", + "#44EE44", + "#4444EE", + "#448844", + "#EE4444", + "#EE44EE", + "#EEEE44", + ); + + my $PNG1 = $u . $myself . "1." . $when . ".png"; + my $PNG2 = $u . $myself . "2." . $when . ".png"; + my $PNG3 = $u . $myself . "3." . $when . ".png"; + my $PNG1z = $u . $myself . "1z." . $when . ".png"; + my $PNG2z = $u . $myself . "2z." . $when . ".png"; + my $PNG3z = $u . $myself . "3z." . $when . ".png"; + + $title = !$silent ? $title : ""; + + unlink ("$PNG_DIR" . "$PNG1", + "$PNG_DIR" . "$PNG2", + "$PNG_DIR" . "$PNG3"); + if($ENABLE_ZOOM eq "Y") { + unlink ("$PNG_DIR" . "$PNG1z", + "$PNG_DIR" . "$PNG2z", + "$PNG_DIR" . "$PNG3z"); + } + + open(IN, "monitorix.hplog"); + my @hplog = ; + close(IN); + + if(!scalar(@hplog)) { + print("WARNING: 'hplog' command output is empty."); + } + if($IFACE_MODE eq "text") { + if($title) { + graph_header($title, 2); + print(" \n"); + print(" \n"); + } + my (undef, undef, undef, $data) = RRDs::fetch("$HPTEMP_RRD", + "--start=-$nwhen$twhen", + "AVERAGE", + "-r $res"); + $err = RRDs::error; + print("ERROR: while fetching $HPTEMP_RRD: $err\n") if $err; + my $str; + my $line1; + my $line2; + print("
\n");
+		foreach my $t (@HPTEMP_1, @HPTEMP_2, @HPTEMP_3) {
+			$id = sprintf("%2d", $t);
+			for($n = 0; $n < scalar(@hplog); $n++) {
+				$_ = $hplog[$n];
+				if(/^$id  /) {
+					$str = substr($_, 17, 8);
+					$str = sprintf("%8s", $str);
+					$line1 .= "  ";
+					$line1 .= $str;
+					$line2 .= "----------";
+				}
+			}
+		}
+		print("Time $line1 \n");
+		print("-----$line2\n");
+		my $line;
+		my @row;
+		my $time;
+		my $n2;
+		for($n = 0, $time = $tb; $n < ($tb * $ts); $n++) {
+			$line = @$data[$n];
+			$time = $time - (1 / $ts);
+			printf(" %2d$tc ", $time);
+			undef($line1);
+			undef(@row);
+			for($n2 = 0; $n2 < scalar(@HPTEMP_1); $n2++) {
+				my $temp = @$line[$n2];
+				push(@row, $temp);
+				$line1 .= " %8.0f ";
+			}
+			for($n2 = 0; $n2 < scalar(@HPTEMP_2); $n2++) {
+				my $temp = @$line[8 + $n2];
+				push(@row, $temp);
+				$line1 .= " %8.0f ";
+			}
+			for($n2 = 0; $n2 < scalar(@HPTEMP_3); $n2++) {
+				my $temp = @$line[8 + 3 + $n2];
+				push(@row, $temp);
+				$line1 .= " %8.0f ";
+			}
+			print(sprintf($line1, @row));
+			print("\n");
+		}
+		print("    
\n"); + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; + } + + if($title) { + graph_header($title, 2); + print(" \n"); + print(" \n"); + } + + if(scalar(@HPTEMP_1)) { + undef(@tmp); + undef(@tmpz); + for($n = 0; $n < 8; $n++) { + if($HPTEMP_1[$n]) { + foreach $_ (@hplog) { + $id = sprintf("%2d", $HPTEMP_1[$n]); + if(/^$id /) { + $str = substr($_, 17, 8); + $str = sprintf("%-20s", $str); + push(@tmp, "LINE2:temp" . $n . $LC[$n] . ":$str"); + push(@tmp, "GPRINT:temp" . $n . ":LAST:Current\\: %2.0lf"); + push(@tmp, "GPRINT:temp" . $n . ":AVERAGE: Average\\: %2.0lf"); + push(@tmp, "GPRINT:temp" . $n . ":MIN: Min\\: %2.0lf"); + push(@tmp, "GPRINT:temp" . $n . ":MAX: Max\\: %2.0lf\\n"); + $str =~ s/\s+$//; + push(@tmpz, "LINE2:temp" . $n . $LC[$n] . ":$str"); + last; + } + } + } else { + push(@tmp, "COMMENT: \\n"); + } + } + ($width, $height) = split('x', $GRAPH_SIZE{main}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + } + RRDs::graph("$PNG_DIR" . "$PNG1", + "--title=$rgraphs{_hptemp1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Celsius", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:temp0=$HPTEMP_RRD:hptemp1_1:AVERAGE", + "DEF:temp1=$HPTEMP_RRD:hptemp1_2:AVERAGE", + "DEF:temp2=$HPTEMP_RRD:hptemp1_3:AVERAGE", + "DEF:temp3=$HPTEMP_RRD:hptemp1_4:AVERAGE", + "DEF:temp4=$HPTEMP_RRD:hptemp1_5:AVERAGE", + "DEF:temp5=$HPTEMP_RRD:hptemp1_6:AVERAGE", + "DEF:temp6=$HPTEMP_RRD:hptemp1_7:AVERAGE", + "DEF:temp7=$HPTEMP_RRD:hptemp1_8:AVERAGE", + @tmp, + "COMMENT: \\n"); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG1: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG1z", + "--title=$rgraphs{_hptemp1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Celsius", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:temp0=$HPTEMP_RRD:hptemp1_1:AVERAGE", + "DEF:temp1=$HPTEMP_RRD:hptemp1_2:AVERAGE", + "DEF:temp2=$HPTEMP_RRD:hptemp1_3:AVERAGE", + "DEF:temp3=$HPTEMP_RRD:hptemp1_4:AVERAGE", + "DEF:temp4=$HPTEMP_RRD:hptemp1_5:AVERAGE", + "DEF:temp5=$HPTEMP_RRD:hptemp1_6:AVERAGE", + "DEF:temp6=$HPTEMP_RRD:hptemp1_7:AVERAGE", + "DEF:temp7=$HPTEMP_RRD:hptemp1_8:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG1z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /hptemp1/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + } + + if($title) { + print(" \n"); + print(" \n"); + } + + if(scalar(@HPTEMP_2)) { + undef(@tmp); + undef(@tmpz); + for($n = 0; $n < 6; $n++) { + if($HPTEMP_2[$n]) { + foreach $_ (@hplog) { + $id = sprintf("%2d", $HPTEMP_2[$n]); + if(/^$id /) { + $str = substr($_, 17, 8); + $str = sprintf("%-8s", $str); + push(@tmp, "LINE2:temp" . $n . $LC[$n] . ":$str"); + push(@tmp, "GPRINT:temp" . $n . ":LAST:\\: %2.0lf"); + if(!(($n + 1) % 2)) { + push(@tmp, "COMMENT: \\n"); + } else { + push(@tmp, "COMMENT: "); + } + $str =~ s/\s+$//; + push(@tmpz, "LINE2:temp" . $n . $LC[$n] . ":$str"); + last; + } + } + } else { + push(@tmp, "COMMENT: \\n") unless ($n + 1) % 2; + } + } + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + } + RRDs::graph("$PNG_DIR" . "$PNG2", + "--title=$rgraphs{_hptemp2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Celsius", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:temp0=$HPTEMP_RRD:hptemp2_1:AVERAGE", + "DEF:temp1=$HPTEMP_RRD:hptemp2_2:AVERAGE", + "DEF:temp2=$HPTEMP_RRD:hptemp2_3:AVERAGE", + "DEF:temp3=$HPTEMP_RRD:hptemp2_4:AVERAGE", + "DEF:temp4=$HPTEMP_RRD:hptemp2_5:AVERAGE", + "DEF:temp5=$HPTEMP_RRD:hptemp2_6:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG2: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG2z", + "--title=$rgraphs{_hptemp2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Celsius", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:temp0=$HPTEMP_RRD:hptemp2_1:AVERAGE", + "DEF:temp1=$HPTEMP_RRD:hptemp2_2:AVERAGE", + "DEF:temp2=$HPTEMP_RRD:hptemp2_3:AVERAGE", + "DEF:temp3=$HPTEMP_RRD:hptemp2_4:AVERAGE", + "DEF:temp4=$HPTEMP_RRD:hptemp2_5:AVERAGE", + "DEF:temp5=$HPTEMP_RRD:hptemp2_6:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG2z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /hptemp2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + } + + if(scalar(@HPTEMP_3)) { + undef(@tmp); + undef(@tmpz); + for($n = 0; $n < 6; $n++) { + if($HPTEMP_3[$n]) { + foreach $_ (@hplog) { + $id = sprintf("%2d", $HPTEMP_3[$n]); + if(/^$id /) { + $str = substr($_, 17, 8); + $str = sprintf("%-8s", $str); + push(@tmp, "LINE2:temp" . $n . $LC[$n] . ":$str"); + push(@tmp, "GPRINT:temp" . $n . ":LAST:\\: %2.0lf"); + if(!(($n + 1) % 2)) { + push(@tmp, "COMMENT: \\n"); + } else { + push(@tmp, "COMMENT: "); + } + $str =~ s/\s+$//; + push(@tmpz, "LINE2:temp" . $n . $LC[$n] . ":$str"); + last; + } + } + } else { + push(@tmp, "COMMENT: \\n") unless ($n + 1) % 2; + } + } + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + } + RRDs::graph("$PNG_DIR" . "$PNG3", + "--title=$rgraphs{_hptemp3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Celsius", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:temp0=$HPTEMP_RRD:hptemp3_1:AVERAGE", + "DEF:temp1=$HPTEMP_RRD:hptemp3_2:AVERAGE", + "DEF:temp2=$HPTEMP_RRD:hptemp3_3:AVERAGE", + "DEF:temp3=$HPTEMP_RRD:hptemp3_4:AVERAGE", + "DEF:temp4=$HPTEMP_RRD:hptemp3_5:AVERAGE", + "DEF:temp5=$HPTEMP_RRD:hptemp3_6:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG3: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG3z", + "--title=$rgraphs{_hptemp3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Celsius", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:temp0=$HPTEMP_RRD:hptemp3_1:AVERAGE", + "DEF:temp1=$HPTEMP_RRD:hptemp3_2:AVERAGE", + "DEF:temp2=$HPTEMP_RRD:hptemp3_3:AVERAGE", + "DEF:temp3=$HPTEMP_RRD:hptemp3_4:AVERAGE", + "DEF:temp4=$HPTEMP_RRD:hptemp3_5:AVERAGE", + "DEF:temp5=$HPTEMP_RRD:hptemp3_6:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG3z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /hptemp3/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + } + + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; +} + +# LMSENS graph +# ---------------------------------------------------------------------------- +sub lmsens { + my ($myself, $title) = @_; + + my $width; + my $height; + my @tmp; + my @tmpz; + my $vlabel; + my $n; + my $str; + my $err; + my @LC = ( + "#FFA500", + "#44EEEE", + "#44EE44", + "#4444EE", + "#448844", + "#EE4444", + "#EE44EE", + "#EEEE44", + "#444444", + "#BB44EE", + "#CCCCCC", + "#B4B444", + "#D3D701", + "#E29136", + "#DDAE8C", + "#F29967", + ); + + my $PNG1 = $u . $myself . "1." . $when . ".png"; + my $PNG2 = $u . $myself . "2." . $when . ".png"; + my $PNG3 = $u . $myself . "3." . $when . ".png"; + my $PNG4 = $u . $myself . "4." . $when . ".png"; + my $PNG5 = $u . $myself . "5." . $when . ".png"; + my $PNG1z = $u . $myself . "1z." . $when . ".png"; + my $PNG2z = $u . $myself . "2z." . $when . ".png"; + my $PNG3z = $u . $myself . "3z." . $when . ".png"; + my $PNG4z = $u . $myself . "4z." . $when . ".png"; + my $PNG5z = $u . $myself . "5z." . $when . ".png"; + + $title = !$silent ? $title : ""; + + unlink ("$PNG_DIR" . "$PNG1", + "$PNG_DIR" . "$PNG2", + "$PNG_DIR" . "$PNG3", + "$PNG_DIR" . "$PNG4", + "$PNG_DIR" . "$PNG5"); + if($ENABLE_ZOOM eq "Y") { + unlink ("$PNG_DIR" . "$PNG1z", + "$PNG_DIR" . "$PNG2z", + "$PNG_DIR" . "$PNG3z", + "$PNG_DIR" . "$PNG4z", + "$PNG_DIR" . "$PNG5z"); + } + + if($IFACE_MODE eq "text") { + if($title) { + graph_header($title, 2); + print(" \n"); + print(" \n"); + } + my (undef, undef, undef, $data) = RRDs::fetch("$LMSENS_RRD", + "--start=-$nwhen$twhen", + "AVERAGE", + "-r $res"); + $err = RRDs::error; + print("ERROR: while fetching $LMSENS_RRD: $err\n") if $err; + my $line1; + my $line2; + print("
\n");
+		for($n = 0; $n < 2; $n++) {
+			$str = "MB" . $n;
+			if($SENSORS_LIST{$str}) {
+				$line1 .= "  ";
+				$line1 .= sprintf("%15s", substr($SENSORS_LIST{$str}, 0, 15));
+				$line2 .= "-----------------";
+			}
+		}
+		for($n = 0; $n < 4; $n++) {
+			$str = "CPU" . $n;
+			if($SENSORS_LIST{$str}) {
+				$line1 .= "  ";
+				$line1 .= sprintf("%15s", substr($SENSORS_LIST{$str}, 0, 15));
+				$line2 .= "-----------------";
+			}
+		}
+		for($n = 0; $n < 9; $n++) {
+			$str = "FAN" . $n;
+			if($SENSORS_LIST{$str}) {
+				$line1 .= "  ";
+				$line1 .= sprintf("%15s", substr($SENSORS_LIST{$str}, 0, 15));
+				$line2 .= "-----------------";
+			}
+		}
+		for($n = 0; $n < 16; $n++) {
+			$str = "CORE" . $n;
+			if($SENSORS_LIST{$str}) {
+				$line1 .= "  ";
+				$line1 .= sprintf("%15s", substr($SENSORS_LIST{$str}, 0, 15));
+				$line2 .= "-----------------";
+			}
+		}
+		for($n = 0; $n < 12; $n++) {
+			$str = "VOLT" . $n;
+			if($SENSORS_LIST{$str}) {
+				$line1 .= "  ";
+				$line1 .= sprintf("%15s", substr($SENSORS_LIST{$str}, 0, 15));
+				$line2 .= "-----------------";
+			}
+		}
+		for($n = 0; $n < 9; $n++) {
+			$str = "GPU" . $n;
+			if($SENSORS_LIST{$str}) {
+				$line1 .= "  ";
+				$line1 .= sprintf("%15s", substr($SENSORS_LIST{$str}, 0, 15));
+				$line2 .= "-----------------";
+			}
+		}
+		print("Time $line1\n");
+		print("-----$line2\n");
+		my $l;
+		my $line;
+		my @row;
+		my $time;
+		my @mb;
+		my @cpu;
+		my @fan;
+		my @core;
+		my @volt;
+		my @gpu;
+		for($l = 0, $time = $tb; $l < ($tb * $ts); $l++) {
+			$line1 = " %2d$tc ";
+			undef(@row);
+			$line = @$data[$l];
+			(@mb[0..2-1], @cpu[0..4-1], @fan[0..10-1], @core[0..16-1], @volt[0..10-1], @gpu[0..8-1]) = @$line;
+			for($n = 0; $n < 2; $n++) {
+				$str = "MB" . $n;
+				if($SENSORS_LIST{$str}) {
+					push(@row, $mb[$n]);
+					$line1 .= "  ";
+					$line1 .= "%15.1f";
+				}
+			}
+			for($n = 0; $n < 4; $n++) {
+				$str = "CPU" . $n;
+				if($SENSORS_LIST{$str}) {
+					push(@row, $cpu[$n]);
+					$line1 .= "  ";
+					$line1 .= "%15.1f";
+				}
+			}
+			for($n = 0; $n < 9; $n++) {
+				$str = "FAN" . $n;
+				if($SENSORS_LIST{$str}) {
+					push(@row, $fan[$n]);
+					$line1 .= "  ";
+					$line1 .= "%15.1f";
+				}
+			}
+			for($n = 0; $n < 16; $n++) {
+				$str = "CORE" . $n;
+				if($SENSORS_LIST{$str}) {
+					push(@row, $core[$n]);
+					$line1 .= "  ";
+					$line1 .= "%15.1f";
+				}
+			}
+			for($n = 0; $n < 12; $n++) {
+				$str = "VOLT" . $n;
+				if($SENSORS_LIST{$str}) {
+					push(@row, $volt[$n]);
+					$line1 .= "  ";
+					$line1 .= "%15.1f";
+				}
+			}
+			for($n = 0; $n < 9; $n++) {
+				$str = "GPU" . $n;
+				if($SENSORS_LIST{$str}) {
+					push(@row, $gpu[$n]);
+					$line1 .= "  ";
+					$line1 .= "%15.1f";
+				}
+			}
+			$time = $time - (1 / $ts);
+			printf("$line1 \n", $time, @row);
+		}
+		print("    
\n"); + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; + } + + if($title) { + my $n2; + graph_header($title, 2); + } + for($n = 0; $n < 4; $n++) { + for($n2 = $n; $n2 < 16; $n2 += 4) { + $str = "CORE" . $n2; + if($SENSORS_LIST{$str}) { + $str = sprintf("Core %2d", $n2); + push(@tmp, "LINE2:core$n2" . $LC[$n2] . ":$str\\g"); + push(@tmp, "GPRINT:core$n2:LAST:\\:%3.0lf "); + } + } + push(@tmp, "COMMENT: \\n") unless !@tmp; + } + for($n = 0; $n < 16; $n++) { + $str = "CORE" . $n; + if($SENSORS_LIST{$str}) { + $str = sprintf("Core %d", $n); + push(@tmpz, "LINE2:core$n" . $LC[$n] . ":$str"); + } + } + # if no COREs are defined then create a blank graph + if(!@tmp) { + push(@tmp, "GPRINT:core0:LAST:%0.0lf"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmpz, "GPRINT:core0:LAST:%0.0lf"); + } + if($title) { + print(" \n"); + print(" \n"); + } + ($width, $height) = split('x', $GRAPH_SIZE{main}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG1", + "--title=$rgraphs{_lmsens1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Celsius", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:core0=$LMSENS_RRD:lmsens_core0:AVERAGE", + "DEF:core1=$LMSENS_RRD:lmsens_core1:AVERAGE", + "DEF:core2=$LMSENS_RRD:lmsens_core2:AVERAGE", + "DEF:core3=$LMSENS_RRD:lmsens_core3:AVERAGE", + "DEF:core4=$LMSENS_RRD:lmsens_core4:AVERAGE", + "DEF:core5=$LMSENS_RRD:lmsens_core5:AVERAGE", + "DEF:core6=$LMSENS_RRD:lmsens_core6:AVERAGE", + "DEF:core7=$LMSENS_RRD:lmsens_core7:AVERAGE", + "DEF:core8=$LMSENS_RRD:lmsens_core8:AVERAGE", + "DEF:core9=$LMSENS_RRD:lmsens_core9:AVERAGE", + "DEF:core10=$LMSENS_RRD:lmsens_core10:AVERAGE", + "DEF:core11=$LMSENS_RRD:lmsens_core11:AVERAGE", + "DEF:core12=$LMSENS_RRD:lmsens_core12:AVERAGE", + "DEF:core13=$LMSENS_RRD:lmsens_core13:AVERAGE", + "DEF:core14=$LMSENS_RRD:lmsens_core14:AVERAGE", + "DEF:core15=$LMSENS_RRD:lmsens_core15:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG1: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG1z", + "--title=$rgraphs{_lmsens1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Celsius", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:core0=$LMSENS_RRD:lmsens_core0:AVERAGE", + "DEF:core1=$LMSENS_RRD:lmsens_core1:AVERAGE", + "DEF:core2=$LMSENS_RRD:lmsens_core2:AVERAGE", + "DEF:core3=$LMSENS_RRD:lmsens_core3:AVERAGE", + "DEF:core4=$LMSENS_RRD:lmsens_core4:AVERAGE", + "DEF:core5=$LMSENS_RRD:lmsens_core5:AVERAGE", + "DEF:core6=$LMSENS_RRD:lmsens_core6:AVERAGE", + "DEF:core7=$LMSENS_RRD:lmsens_core7:AVERAGE", + "DEF:core8=$LMSENS_RRD:lmsens_core8:AVERAGE", + "DEF:core9=$LMSENS_RRD:lmsens_core9:AVERAGE", + "DEF:core10=$LMSENS_RRD:lmsens_core10:AVERAGE", + "DEF:core11=$LMSENS_RRD:lmsens_core11:AVERAGE", + "DEF:core12=$LMSENS_RRD:lmsens_core12:AVERAGE", + "DEF:core13=$LMSENS_RRD:lmsens_core13:AVERAGE", + "DEF:core14=$LMSENS_RRD:lmsens_core14:AVERAGE", + "DEF:core15=$LMSENS_RRD:lmsens_core15:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG1z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /lmsens1/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@tmp); + undef(@tmpz); + $SENSORS_LIST{'VOLT0'} =~ s/\\//; + $str = $SENSORS_LIST{'VOLT0'} ? sprintf("%8s", substr($SENSORS_LIST{'VOLT0'}, 0, 8)) : ""; + push(@tmp, ("LINE2:volt0#FFA500:$str\\g", "GPRINT:volt0:LAST:\\:%6.2lf ")); + $SENSORS_LIST{'VOLT3'} =~ s/\\//; + $str = $SENSORS_LIST{'VOLT3'} ? sprintf("%8s", substr($SENSORS_LIST{'VOLT3'}, 0, 8)) : ""; + push(@tmp, ("LINE2:volt3#4444EE:$str\\g", "GPRINT:volt3:LAST:\\:%6.2lf ")) unless !$str; + $SENSORS_LIST{'VOLT6'} =~ s/\\//; + $str = $SENSORS_LIST{'VOLT6'} ? sprintf("%8s", substr($SENSORS_LIST{'VOLT6'}, 0, 8)) : ""; + push(@tmp, ("LINE2:volt6#EE44EE:$str\\g", "GPRINT:volt6:LAST:\\:%6.2lf ")) unless !$str; + $SENSORS_LIST{'VOLT9'} =~ s/\\//; + $str = $SENSORS_LIST{'VOLT9'} ? sprintf("%8s", substr($SENSORS_LIST{'VOLT9'}, 0, 8)) : ""; + push(@tmp, ("LINE2:volt9#94C36B:$str\\g", "GPRINT:volt9:LAST:\\:%6.2lf\\g")) unless !$str; + push(@tmp, "COMMENT: \\n"); + $SENSORS_LIST{'VOLT1'} =~ s/\\//; + $str = $SENSORS_LIST{'VOLT1'} ? sprintf("%8s", substr($SENSORS_LIST{'VOLT1'}, 0, 8)) : ""; + push(@tmp, ("LINE2:volt1#44EEEE:$str\\g", "GPRINT:volt1:LAST:\\:%6.2lf ")) unless !$str; + $SENSORS_LIST{'VOLT4'} =~ s/\\//; + $str = $SENSORS_LIST{'VOLT4'} ? sprintf("%8s", substr($SENSORS_LIST{'VOLT4'}, 0, 8)) : ""; + push(@tmp, ("LINE2:volt4#448844:$str\\g", "GPRINT:volt4:LAST:\\:%6.2lf ")) unless !$str; + $SENSORS_LIST{'VOLT7'} =~ s/\\//; + $str = $SENSORS_LIST{'VOLT7'} ? sprintf("%8s", substr($SENSORS_LIST{'VOLT7'}, 0, 8)) : ""; + push(@tmp, ("LINE2:volt7#EEEE44:$str\\g", "GPRINT:volt7:LAST:\\:%6.2lf ")) unless !$str; + $SENSORS_LIST{'VOLT10'} =~ s/\\//; + $str = $SENSORS_LIST{'VOLT10'} ? sprintf("%8s", substr($SENSORS_LIST{'VOLT10'}, 0, 8)) : ""; + push(@tmp, ("LINE2:volt10#3CB5B0:$str\\g", "GPRINT:volt10:LAST:\\:%6.2lf\\g")) unless !$str; + push(@tmp, "COMMENT: \\n"); + $SENSORS_LIST{'VOLT2'} =~ s/\\//; + $str = $SENSORS_LIST{'VOLT2'} ? sprintf("%8s", substr($SENSORS_LIST{'VOLT2'}, 0, 8)) : ""; + push(@tmp, ("LINE2:volt2#44EE44:$str\\g", "GPRINT:volt2:LAST:\\:%6.2lf ")) unless !$str; + $SENSORS_LIST{'VOLT5'} =~ s/\\//; + $str = $SENSORS_LIST{'VOLT5'} ? sprintf("%8s", substr($SENSORS_LIST{'VOLT5'}, 0, 8)) : ""; + push(@tmp, ("LINE2:volt5#EE4444:$str\\g", "GPRINT:volt5:LAST:\\:%6.2lf ")) unless !$str; + $SENSORS_LIST{'VOLT8'} =~ s/\\//; + $str = $SENSORS_LIST{'VOLT8'} ? sprintf("%8s", substr($SENSORS_LIST{'VOLT8'}, 0, 8)) : ""; + push(@tmp, ("LINE2:volt8#963C74:$str\\g", "GPRINT:volt8:LAST:\\:%6.2lf ")) unless !$str; + $SENSORS_LIST{'VOLT11'} =~ s/\\//; + $str = $SENSORS_LIST{'VOLT11'} ? sprintf("%8s", substr($SENSORS_LIST{'VOLT11'}, 0, 8)) : ""; + push(@tmp, ("LINE2:volt11#597AB7:$str\\g", "GPRINT:volt11:LAST:\\:%6.2lf\\g")) unless !$str; + push(@tmp, "COMMENT: \\n"); + $str = $SENSORS_LIST{'VOLT0'} ? substr($SENSORS_LIST{'VOLT0'}, 0, 8) : ""; + push(@tmpz, "LINE2:volt0#FFA500:$str"); + $str = $SENSORS_LIST{'VOLT1'} ? substr($SENSORS_LIST{'VOLT1'}, 0, 8) : ""; + push(@tmpz, "LINE2:volt1#44EEEE:$str")unless !$str; + $str = $SENSORS_LIST{'VOLT2'} ? substr($SENSORS_LIST{'VOLT2'}, 0, 8) : ""; + push(@tmpz, "LINE2:volt2#44EE44:$str")unless !$str; + $str = $SENSORS_LIST{'VOLT3'} ? substr($SENSORS_LIST{'VOLT3'}, 0, 8) : ""; + push(@tmpz, "LINE2:volt3#4444EE:$str")unless !$str; + $str = $SENSORS_LIST{'VOLT4'} ? substr($SENSORS_LIST{'VOLT4'}, 0, 8) : ""; + push(@tmpz, "LINE2:volt4#448844:$str")unless !$str; + $str = $SENSORS_LIST{'VOLT5'} ? substr($SENSORS_LIST{'VOLT5'}, 0, 8) : ""; + push(@tmpz, "LINE2:volt5#EE4444:$str")unless !$str; + $str = $SENSORS_LIST{'VOLT6'} ? substr($SENSORS_LIST{'VOLT6'}, 0, 8) : ""; + push(@tmpz, "LINE2:volt6#EE44EE:$str")unless !$str; + $str = $SENSORS_LIST{'VOLT7'} ? substr($SENSORS_LIST{'VOLT7'}, 0, 8) : ""; + push(@tmpz, "LINE2:volt7#EEEE44:$str")unless !$str; + $str = $SENSORS_LIST{'VOLT8'} ? substr($SENSORS_LIST{'VOLT8'}, 0, 8) : ""; + push(@tmpz, "LINE2:volt8#963C74:$str")unless !$str; + $str = $SENSORS_LIST{'VOLT9'} ? substr($SENSORS_LIST{'VOLT9'}, 0, 8) : ""; + push(@tmpz, "LINE2:volt9#94C36B:$str")unless !$str; + $str = $SENSORS_LIST{'VOLT10'} ? substr($SENSORS_LIST{'VOLT10'}, 0, 8) : ""; + push(@tmpz, "LINE2:volt10#3CB5B0:$str")unless !$str; + $str = $SENSORS_LIST{'VOLT11'} ? substr($SENSORS_LIST{'VOLT11'}, 0, 8) : ""; + push(@tmpz, "LINE2:volt11#597AB7:$str") unless !$str; + ($width, $height) = split('x', $GRAPH_SIZE{main}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG2", + "--title=$rgraphs{_lmsens2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Volts", + "--width=$width", + "--height=$height", + @VERSION12, + @graph_colors, + "DEF:volt0=$LMSENS_RRD:lmsens_volt0:AVERAGE", + "DEF:volt1=$LMSENS_RRD:lmsens_volt1:AVERAGE", + "DEF:volt2=$LMSENS_RRD:lmsens_volt2:AVERAGE", + "DEF:volt3=$LMSENS_RRD:lmsens_volt3:AVERAGE", + "DEF:volt4=$LMSENS_RRD:lmsens_volt4:AVERAGE", + "DEF:volt5=$LMSENS_RRD:lmsens_volt5:AVERAGE", + "DEF:volt6=$LMSENS_RRD:lmsens_volt6:AVERAGE", + "DEF:volt7=$LMSENS_RRD:lmsens_volt7:AVERAGE", + "DEF:volt8=$LMSENS_RRD:lmsens_volt8:AVERAGE", + "DEF:volt9=$LMSENS_RRD:lmsens_volt9:AVERAGE", + "DEF:volt10=$LMSENS_RRD:lmsens_volt10:AVERAGE", + "DEF:volt11=$LMSENS_RRD:lmsens_volt11:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG2: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG2z", + "--title=$rgraphs{_lmsens2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Volts", + "--width=$width", + "--height=$height", + @VERSION12, + @graph_colors, + "DEF:volt0=$LMSENS_RRD:lmsens_volt0:AVERAGE", + "DEF:volt1=$LMSENS_RRD:lmsens_volt1:AVERAGE", + "DEF:volt2=$LMSENS_RRD:lmsens_volt2:AVERAGE", + "DEF:volt3=$LMSENS_RRD:lmsens_volt3:AVERAGE", + "DEF:volt4=$LMSENS_RRD:lmsens_volt4:AVERAGE", + "DEF:volt5=$LMSENS_RRD:lmsens_volt5:AVERAGE", + "DEF:volt6=$LMSENS_RRD:lmsens_volt6:AVERAGE", + "DEF:volt7=$LMSENS_RRD:lmsens_volt7:AVERAGE", + "DEF:volt8=$LMSENS_RRD:lmsens_volt8:AVERAGE", + "DEF:volt9=$LMSENS_RRD:lmsens_volt9:AVERAGE", + "DEF:volt10=$LMSENS_RRD:lmsens_volt10:AVERAGE", + "DEF:volt11=$LMSENS_RRD:lmsens_volt11:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG2z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /lmsens2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + if($title) { + print(" \n"); + print(" \n"); + } + + undef(@tmp); + undef(@tmpz); + push(@tmp, ("LINE2:mb0#FFA500:MB 0\\g", "GPRINT:mb0:LAST:\\:%3.0lf ")); + push(@tmp, ("LINE2:cpu0#4444EE:CPU 0\\g", "GPRINT:cpu0:LAST:\\:%3.0lf ")) unless !$SENSORS_LIST{'CPU0'}; + push(@tmp, ("LINE2:cpu2#EE44EE:CPU 2\\g", "GPRINT:cpu2:LAST:\\:%3.0lf\\g")) unless !$SENSORS_LIST{'CPU2'}; + push(@tmp, "COMMENT: \\n"); + push(@tmp, ("LINE2:mb1#44EEEE:MB 1\\g", "GPRINT:mb1:LAST:\\:%3.0lf ")) unless !$SENSORS_LIST{'MB1'}; + push(@tmp, ("LINE2:cpu1#EEEE44:CPU 1\\g", "GPRINT:cpu1:LAST:\\:%3.0lf ")) unless !$SENSORS_LIST{'CPU1'}; + push(@tmp, ("LINE2:cpu3#44EE44:CPU 3\\g", "GPRINT:cpu3:LAST:\\:%3.0lf\\g")) unless !$SENSORS_LIST{'CPU3'}; + push(@tmp, "COMMENT: \\n"); + push(@tmpz, "LINE2:mb0#FFA500:MB 0"); + push(@tmpz, "LINE2:mb1#44EEEE:MB 1") unless !$SENSORS_LIST{'MB1'}; + push(@tmpz, "LINE2:cpu0#4444EE:CPU 0") unless !$SENSORS_LIST{'CPU0'}; + push(@tmpz, "LINE2:cpu1#EEEE44:CPU 1") unless !$SENSORS_LIST{'CPU1'}; + push(@tmpz, "LINE2:cpu2#EE44EE:CPU 2") unless !$SENSORS_LIST{'CPU2'}; + push(@tmpz, "LINE2:cpu3#44EE44:CPU 3") unless !$SENSORS_LIST{'CPU3'}; + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG3", + "--title=$rgraphs{_lmsens3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Celsius", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:mb0=$LMSENS_RRD:lmsens_mb0:AVERAGE", + "DEF:mb1=$LMSENS_RRD:lmsens_mb1:AVERAGE", + "DEF:cpu0=$LMSENS_RRD:lmsens_cpu0:AVERAGE", + "DEF:cpu1=$LMSENS_RRD:lmsens_cpu1:AVERAGE", + "DEF:cpu2=$LMSENS_RRD:lmsens_cpu2:AVERAGE", + "DEF:cpu3=$LMSENS_RRD:lmsens_cpu3:AVERAGE", + "COMMENT: \\n", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG3: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG3z", + "--title=$rgraphs{_lmsens3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Celsius", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:mb0=$LMSENS_RRD:lmsens_mb0:AVERAGE", + "DEF:mb1=$LMSENS_RRD:lmsens_mb1:AVERAGE", + "DEF:cpu0=$LMSENS_RRD:lmsens_cpu0:AVERAGE", + "DEF:cpu1=$LMSENS_RRD:lmsens_cpu1:AVERAGE", + "DEF:cpu2=$LMSENS_RRD:lmsens_cpu2:AVERAGE", + "DEF:cpu3=$LMSENS_RRD:lmsens_cpu3:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG3z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /lmsens3/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@tmp); + undef(@tmpz); + push(@tmp, ("LINE2:fan0#FFA500:Fan 0\\g", "GPRINT:fan0:LAST:\\:%5.0lf")); + push(@tmp, ("LINE2:fan3#4444EE:Fan 3\\g", "GPRINT:fan3:LAST:\\:%5.0lf")) unless !$SENSORS_LIST{'FAN3'}; + push(@tmp, ("LINE2:fan6#EE44EE:Fan 6\\g", "GPRINT:fan6:LAST:\\:%5.0lf\\g")) unless !$SENSORS_LIST{'FAN6'}; + push(@tmp, "COMMENT: \\n"); + push(@tmp, ("LINE2:fan1#44EEEE:Fan 1\\g", "GPRINT:fan1:LAST:\\:%5.0lf")) unless !$SENSORS_LIST{'FAN1'}; + push(@tmp, ("LINE2:fan4#448844:Fan 4\\g", "GPRINT:fan4:LAST:\\:%5.0lf")) unless !$SENSORS_LIST{'FAN4'}; + push(@tmp, ("LINE2:fan7#EEEE44:Fan 7\\g", "GPRINT:fan7:LAST:\\:%5.0lf\\g")) unless !$SENSORS_LIST{'FAN7'}; + push(@tmp, "COMMENT: \\n"); + push(@tmp, ("LINE2:fan2#44EE44:Fan 2\\g", "GPRINT:fan2:LAST:\\:%5.0lf")) unless !$SENSORS_LIST{'FAN2'}; + push(@tmp, ("LINE2:fan5#EE4444:Fan 5\\g", "GPRINT:fan5:LAST:\\:%5.0lf")) unless !$SENSORS_LIST{'FAN5'}; + push(@tmp, ("LINE2:fan8#963C74:Fan 8\\g", "GPRINT:fan8:LAST:\\:%5.0lf\\g")) unless !$SENSORS_LIST{'FAN8'}; + push(@tmp, "COMMENT: \\n"); + push(@tmpz, "LINE2:fan0#FFA500:Fan 0"); + push(@tmpz, "LINE2:fan1#44EEEE:Fan 1") unless !$SENSORS_LIST{'FAN1'}; + push(@tmpz, "LINE2:fan2#44EE44:Fan 2") unless !$SENSORS_LIST{'FAN2'}; + push(@tmpz, "LINE2:fan3#4444EE:Fan 3") unless !$SENSORS_LIST{'FAN3'}; + push(@tmpz, "LINE2:fan4#448844:Fan 4") unless !$SENSORS_LIST{'FAN4'}; + push(@tmpz, "LINE2:fan5#EE4444:Fan 5") unless !$SENSORS_LIST{'FAN5'}; + push(@tmpz, "LINE2:fan6#EE44EE:Fan 6") unless !$SENSORS_LIST{'FAN6'}; + push(@tmpz, "LINE2:fan7#EEEE44:Fan 7") unless !$SENSORS_LIST{'FAN7'}; + push(@tmpz, "LINE2:fan8#963C74:Fan 8") unless !$SENSORS_LIST{'FAN8'}; + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG4", + "--title=$rgraphs{_lmsens4} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=RPM", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:fan0=$LMSENS_RRD:lmsens_fan0:AVERAGE", + "DEF:fan1=$LMSENS_RRD:lmsens_fan1:AVERAGE", + "DEF:fan2=$LMSENS_RRD:lmsens_fan2:AVERAGE", + "DEF:fan3=$LMSENS_RRD:lmsens_fan3:AVERAGE", + "DEF:fan4=$LMSENS_RRD:lmsens_fan4:AVERAGE", + "DEF:fan5=$LMSENS_RRD:lmsens_fan5:AVERAGE", + "DEF:fan6=$LMSENS_RRD:lmsens_fan6:AVERAGE", + "DEF:fan7=$LMSENS_RRD:lmsens_fan7:AVERAGE", + "DEF:fan8=$LMSENS_RRD:lmsens_fan8:AVERAGE", + "COMMENT: \\n", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG4: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG4z", + "--title=$rgraphs{_lmsens4} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=RPM", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:fan0=$LMSENS_RRD:lmsens_fan0:AVERAGE", + "DEF:fan1=$LMSENS_RRD:lmsens_fan1:AVERAGE", + "DEF:fan2=$LMSENS_RRD:lmsens_fan2:AVERAGE", + "DEF:fan3=$LMSENS_RRD:lmsens_fan3:AVERAGE", + "DEF:fan4=$LMSENS_RRD:lmsens_fan4:AVERAGE", + "DEF:fan5=$LMSENS_RRD:lmsens_fan5:AVERAGE", + "DEF:fan6=$LMSENS_RRD:lmsens_fan6:AVERAGE", + "DEF:fan7=$LMSENS_RRD:lmsens_fan7:AVERAGE", + "DEF:fan8=$LMSENS_RRD:lmsens_fan8:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG4z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /lmsens4/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@tmp); + undef(@tmpz); + push(@tmp, "LINE2:gpu0#FFA500:GPU 0\\g"); + push(@tmp, "GPRINT:gpu0:LAST:\\:%3.0lf "); + push(@tmp, ("LINE2:gpu3#4444EE:GPU 3\\g", "GPRINT:gpu3:LAST:\\:%3.0lf ")) unless !$SENSORS_LIST{'GPU3'}; + push(@tmp, ("LINE2:gpu6#EE44EE:GPU 6\\g", "GPRINT:gpu6:LAST:\\:%3.0lf\\g")) unless !$SENSORS_LIST{'GPU6'}; + push(@tmp, "COMMENT: \\n"); + push(@tmp, ("LINE2:gpu1#44EEEE:GPU 1\\g", "GPRINT:gpu1:LAST:\\:%3.0lf ")) unless !$SENSORS_LIST{'GPU1'}; + push(@tmp, ("LINE2:gpu4#448844:GPU 4\\g", "GPRINT:gpu4:LAST:\\:%3.0lf ")) unless !$SENSORS_LIST{'GPU4'}; + push(@tmp, ("LINE2:gpu7#EEEE44:GPU 7\\g", "GPRINT:gpu7:LAST:\\:%3.0lf\\g")) unless !$SENSORS_LIST{'GPU7'}; + push(@tmp, "COMMENT: \\n"); + push(@tmp, ("LINE2:gpu2#44EE44:GPU 2\\g", "GPRINT:gpu2:LAST:\\:%3.0lf ")) unless !$SENSORS_LIST{'GPU2'}; + push(@tmp, ("LINE2:gpu5#EE4444:GPU 5\\g", "GPRINT:gpu5:LAST:\\:%3.0lf ")) unless !$SENSORS_LIST{'GPU5'}; + push(@tmp, ("LINE2:gpu8#963C74:GPU 8\\g", "GPRINT:gpu8:LAST:\\:%3.0lf\\g")) unless !$SENSORS_LIST{'GPU8'}; + push(@tmp, "COMMENT: \\n"); + push(@tmpz, "LINE2:gpu0#FFA500:GPU 0\\g"); + push(@tmpz, "LINE2:gpu1#44EEEE:GPU 1\\g") unless !$SENSORS_LIST{'GPU1'}; + push(@tmpz, "LINE2:gpu2#44EE44:GPU 2\\g") unless !$SENSORS_LIST{'GPU2'}; + push(@tmpz, "LINE2:gpu3#4444EE:GPU 3\\g") unless !$SENSORS_LIST{'GPU3'}; + push(@tmpz, "LINE2:gpu4#448844:GPU 4\\g") unless !$SENSORS_LIST{'GPU4'}; + push(@tmpz, "LINE2:gpu5#EE4444:GPU 5\\g") unless !$SENSORS_LIST{'GPU5'}; + push(@tmpz, "LINE2:gpu6#EE44EE:GPU 6\\g") unless !$SENSORS_LIST{'GPU6'}; + push(@tmpz, "LINE2:gpu7#EEEE44:GPU 7\\g") unless !$SENSORS_LIST{'GPU7'}; + push(@tmpz, "LINE2:gpu8#963C74:GPU 8\\g") unless !$SENSORS_LIST{'GPU8'}; + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG5", + "--title=$rgraphs{_lmsens5} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Celsius", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:gpu0=$LMSENS_RRD:lmsens_gpu0:AVERAGE", + "DEF:gpu1=$LMSENS_RRD:lmsens_gpu1:AVERAGE", + "DEF:gpu2=$LMSENS_RRD:lmsens_gpu2:AVERAGE", + "DEF:gpu3=$LMSENS_RRD:lmsens_gpu3:AVERAGE", + "DEF:gpu4=$LMSENS_RRD:lmsens_gpu4:AVERAGE", + "DEF:gpu5=$LMSENS_RRD:lmsens_gpu5:AVERAGE", + "DEF:gpu6=$LMSENS_RRD:lmsens_gpu6:AVERAGE", + "DEF:gpu7=$LMSENS_RRD:lmsens_gpu7:AVERAGE", + "DEF:gpu8=$LMSENS_RRD:lmsens_gpu8:AVERAGE", + "COMMENT: \\n", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG5: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG5z", + "--title=$rgraphs{_lmsens5} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Celsius", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:gpu0=$LMSENS_RRD:lmsens_gpu0:AVERAGE", + "DEF:gpu1=$LMSENS_RRD:lmsens_gpu1:AVERAGE", + "DEF:gpu2=$LMSENS_RRD:lmsens_gpu2:AVERAGE", + "DEF:gpu3=$LMSENS_RRD:lmsens_gpu3:AVERAGE", + "DEF:gpu4=$LMSENS_RRD:lmsens_gpu4:AVERAGE", + "DEF:gpu5=$LMSENS_RRD:lmsens_gpu5:AVERAGE", + "DEF:gpu6=$LMSENS_RRD:lmsens_gpu6:AVERAGE", + "DEF:gpu7=$LMSENS_RRD:lmsens_gpu7:AVERAGE", + "DEF:gpu8=$LMSENS_RRD:lmsens_gpu8:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG5z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /lmsens5/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; +} + +# NVIDIA graph +# ---------------------------------------------------------------------------- +sub nvidia { + my ($myself, $title) = @_; + + my $width; + my $height; + my @tmp; + my @tmpz; + my $n; + my $err; + my @LC = ( + "#FFA500", + "#44EEEE", + "#44EE44", + "#4444EE", + "#448844", + "#EE4444", + "#EE44EE", + "#EEEE44", + "#963C74", + ); + + my $PNG1 = $u . $myself . "1." . $when . ".png"; + my $PNG2 = $u . $myself . "2." . $when . ".png"; + my $PNG3 = $u . $myself . "3." . $when . ".png"; + my $PNG1z = $u . $myself . "1z." . $when . ".png"; + my $PNG2z = $u . $myself . "2z." . $when . ".png"; + my $PNG3z = $u . $myself . "3z." . $when . ".png"; + + $title = !$silent ? $title : ""; + + unlink ("$PNG_DIR" . "$PNG1", + "$PNG_DIR" . "$PNG2", + "$PNG_DIR" . "$PNG3"); + if($ENABLE_ZOOM eq "Y") { + unlink ("$PNG_DIR" . "$PNG1z", + "$PNG_DIR" . "$PNG2z", + "$PNG_DIR" . "$PNG3z"); + } + + if($IFACE_MODE eq "text") { + if($title) { + graph_header($title, 2); + print(" \n"); + print(" \n"); + } + my (undef, undef, undef, $data) = RRDs::fetch("$NVIDIA_RRD", + "--start=-$nwhen$twhen", + "AVERAGE", + "-r $res"); + $err = RRDs::error; + print("ERROR: while fetching $NVIDIA_RRD: $err\n") if $err; + my $line2; + my $line3; + print("
\n");
+		print("    ");
+		for($n = 0; $n < $NVIDIA_MAX; $n++) {
+			print("   NVIDIA card $n ");
+		}
+		print("\n");
+		for($n = 0; $n < $NVIDIA_MAX; $n++) {
+			$line2 .= "   Temp  GPU  Mem";
+			$line3 .= "-----------------";
+		}
+		print("Time$line2\n");
+		print("----$line3 \n");
+		my $line;
+		my @row;
+		my $time;
+		my $n2;
+		for($n = 0, $time = $tb; $n < ($tb * $ts); $n++) {
+			$line = @$data[$n];
+			$time = $time - (1 / $ts);
+			printf(" %2d$tc ", $time);
+			undef($line1);
+			undef(@row);
+			for($n2 = 0; $n2 < $NVIDIA_MAX; $n2++) {
+				push(@row, @$line[$n2]);
+				push(@row, @$line[$n2 + 9]);
+				push(@row, @$line[$n2 + 18]);
+				$line1 .= "   %3d %3d%% %3d%%";
+			}
+			print(sprintf($line1, @row));
+			print("\n");
+		}
+		print("    
\n"); + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; + } + + if($title) { + graph_header($title, 2); + } + for($n = 0; $n < 9; $n++) { + if($n < $NVIDIA_MAX) { + push(@tmp, "LINE2:temp" . $n . $LC[$n] . ":Card $n"); + push(@tmpz, "LINE2:temp" . $n . $LC[$n] . ":Card $n"); + push(@tmp, "GPRINT:temp" . $n . ":LAST: Current\\: %2.0lf"); + push(@tmp, "GPRINT:temp" . $n . ":AVERAGE: Average\\: %2.0lf"); + push(@tmp, "GPRINT:temp" . $n . ":MIN: Min\\: %2.0lf"); + push(@tmp, "GPRINT:temp" . $n . ":MAX: Max\\: %2.0lf\\n"); + } else { + push(@tmp, "COMMENT: \\n"); + } + } + + if($title) { + print(" \n"); + print(" \n"); + } + ($width, $height) = split('x', $GRAPH_SIZE{main}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG1", + "--title=$rgraphs{_nvidia1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Celsius", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:temp0=$NVIDIA_RRD:nvidia_temp0:AVERAGE", + "DEF:temp1=$NVIDIA_RRD:nvidia_temp1:AVERAGE", + "DEF:temp2=$NVIDIA_RRD:nvidia_temp2:AVERAGE", + "DEF:temp3=$NVIDIA_RRD:nvidia_temp3:AVERAGE", + "DEF:temp4=$NVIDIA_RRD:nvidia_temp4:AVERAGE", + "DEF:temp5=$NVIDIA_RRD:nvidia_temp5:AVERAGE", + "DEF:temp6=$NVIDIA_RRD:nvidia_temp6:AVERAGE", + "DEF:temp7=$NVIDIA_RRD:nvidia_temp7:AVERAGE", + "DEF:temp8=$NVIDIA_RRD:nvidia_temp8:AVERAGE", + @tmp, + "COMMENT: \\n", + "COMMENT: \\n"); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG1: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG1z", + "--title=$rgraphs{_nvidia1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Celsius", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:temp0=$NVIDIA_RRD:nvidia_temp0:AVERAGE", + "DEF:temp1=$NVIDIA_RRD:nvidia_temp1:AVERAGE", + "DEF:temp2=$NVIDIA_RRD:nvidia_temp2:AVERAGE", + "DEF:temp3=$NVIDIA_RRD:nvidia_temp3:AVERAGE", + "DEF:temp4=$NVIDIA_RRD:nvidia_temp4:AVERAGE", + "DEF:temp5=$NVIDIA_RRD:nvidia_temp5:AVERAGE", + "DEF:temp6=$NVIDIA_RRD:nvidia_temp6:AVERAGE", + "DEF:temp7=$NVIDIA_RRD:nvidia_temp7:AVERAGE", + "DEF:temp8=$NVIDIA_RRD:nvidia_temp8:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG1z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /nvidia1/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + if($title) { + print(" \n"); + print(" \n"); + } + + undef(@tmp); + undef(@tmpz); + push(@tmp, "LINE2:gpu0#FFA500:Card 0\\g"); + push(@tmp, "GPRINT:gpu0:LAST:\\:%3.0lf%%"); + push(@tmp, "LINE2:gpu3#4444EE:Card 3\\g"); + push(@tmp, "GPRINT:gpu3:LAST:\\:%3.0lf%%"); + push(@tmp, "LINE2:gpu6#EE44EE:Card 6\\g"); + push(@tmp, "GPRINT:gpu6:LAST:\\:%3.0lf%%\\n"); + push(@tmp, "LINE2:gpu1#44EEEE:Card 1\\g"); + push(@tmp, "GPRINT:gpu1:LAST:\\:%3.0lf%%"); + push(@tmp, "LINE2:gpu4#448844:Card 4\\g"); + push(@tmp, "GPRINT:gpu4:LAST:\\:%3.0lf%%"); + push(@tmp, "LINE2:gpu7#EEEE44:Card 7\\g"); + push(@tmp, "GPRINT:gpu7:LAST:\\:%3.0lf%%\\n"); + push(@tmp, "LINE2:gpu2#44EE44:Card 2\\g"); + push(@tmp, "GPRINT:gpu2:LAST:\\:%3.0lf%%"); + push(@tmp, "LINE2:gpu5#EE4444:Card 5\\g"); + push(@tmp, "GPRINT:gpu5:LAST:\\:%3.0lf%%"); + push(@tmp, "LINE2:gpu8#963C74:Card 8\\g"); + push(@tmp, "GPRINT:gpu8:LAST:\\:%3.0lf%%\\n"); + push(@tmpz, "LINE2:gpu0#FFA500:Card 0"); + push(@tmpz, "LINE2:gpu3#4444EE:Card 3"); + push(@tmpz, "LINE2:gpu6#EE44EE:Card 6"); + push(@tmpz, "LINE2:gpu1#44EEEE:Card 1"); + push(@tmpz, "LINE2:gpu4#448844:Card 4"); + push(@tmpz, "LINE2:gpu7#EEEE44:Card 7"); + push(@tmpz, "LINE2:gpu2#44EE44:Card 2"); + push(@tmpz, "LINE2:gpu5#EE4444:Card 5"); + push(@tmpz, "LINE2:gpu8#963C74:Card 8"); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG2", + "--title=$rgraphs{_nvidia2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Percent", + "--width=$width", + "--height=$height", + "--upper-limit=100", + "--lower-limit=0", + "--rigid", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:gpu0=$NVIDIA_RRD:nvidia_gpu0:AVERAGE", + "DEF:gpu1=$NVIDIA_RRD:nvidia_gpu1:AVERAGE", + "DEF:gpu2=$NVIDIA_RRD:nvidia_gpu2:AVERAGE", + "DEF:gpu3=$NVIDIA_RRD:nvidia_gpu3:AVERAGE", + "DEF:gpu4=$NVIDIA_RRD:nvidia_gpu4:AVERAGE", + "DEF:gpu5=$NVIDIA_RRD:nvidia_gpu5:AVERAGE", + "DEF:gpu6=$NVIDIA_RRD:nvidia_gpu6:AVERAGE", + "DEF:gpu7=$NVIDIA_RRD:nvidia_gpu7:AVERAGE", + "DEF:gpu8=$NVIDIA_RRD:nvidia_gpu8:AVERAGE", + "COMMENT: \\n", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG2: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG2z", + "--title=$rgraphs{_nvidia2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Percent", + "--width=$width", + "--height=$height", + "--upper-limit=100", + "--lower-limit=0", + "--rigid", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:gpu0=$NVIDIA_RRD:nvidia_gpu0:AVERAGE", + "DEF:gpu1=$NVIDIA_RRD:nvidia_gpu1:AVERAGE", + "DEF:gpu2=$NVIDIA_RRD:nvidia_gpu2:AVERAGE", + "DEF:gpu3=$NVIDIA_RRD:nvidia_gpu3:AVERAGE", + "DEF:gpu4=$NVIDIA_RRD:nvidia_gpu4:AVERAGE", + "DEF:gpu5=$NVIDIA_RRD:nvidia_gpu5:AVERAGE", + "DEF:gpu6=$NVIDIA_RRD:nvidia_gpu6:AVERAGE", + "DEF:gpu7=$NVIDIA_RRD:nvidia_gpu7:AVERAGE", + "DEF:gpu8=$NVIDIA_RRD:nvidia_gpu8:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG2z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /nvidia2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@tmp); + undef(@tmpz); + push(@tmp, "LINE2:mem0#FFA500:Card 0\\g"); + push(@tmp, "GPRINT:mem0:LAST:\\:%3.0lf%%"); + push(@tmp, "LINE2:mem3#4444EE:Card 3\\g"); + push(@tmp, "GPRINT:mem3:LAST:\\:%3.0lf%%"); + push(@tmp, "LINE2:mem6#EE44EE:Card 6\\g"); + push(@tmp, "GPRINT:mem6:LAST:\\:%3.0lf%%\\n"); + push(@tmp, "LINE2:mem1#44EEEE:Card 1\\g"); + push(@tmp, "GPRINT:mem1:LAST:\\:%3.0lf%%"); + push(@tmp, "LINE2:mem4#448844:Card 4\\g"); + push(@tmp, "GPRINT:mem4:LAST:\\:%3.0lf%%"); + push(@tmp, "LINE2:mem7#EEEE44:Card 7\\g"); + push(@tmp, "GPRINT:mem7:LAST:\\:%3.0lf%%\\n"); + push(@tmp, "LINE2:mem2#44EE44:Card 2\\g"); + push(@tmp, "GPRINT:mem2:LAST:\\:%3.0lf%%"); + push(@tmp, "LINE2:mem5#EE4444:Card 5\\g"); + push(@tmp, "GPRINT:mem5:LAST:\\:%3.0lf%%"); + push(@tmp, "LINE2:mem8#963C74:Card 8\\g"); + push(@tmp, "GPRINT:mem8:LAST:\\:%3.0lf%%\\n"); + push(@tmpz, "LINE2:mem0#FFA500:Card 0"); + push(@tmpz, "LINE2:mem3#4444EE:Card 3"); + push(@tmpz, "LINE2:mem6#EE44EE:Card 6"); + push(@tmpz, "LINE2:mem1#44EEEE:Card 1"); + push(@tmpz, "LINE2:mem4#448844:Card 4"); + push(@tmpz, "LINE2:mem7#EEEE44:Card 7"); + push(@tmpz, "LINE2:mem2#44EE44:Card 2"); + push(@tmpz, "LINE2:mem5#EE4444:Card 5"); + push(@tmpz, "LINE2:mem8#963C74:Card 8"); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG3", + "--title=$rgraphs{_nvidia3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Percent", + "--width=$width", + "--height=$height", + "--upper-limit=100", + "--lower-limit=0", + "--rigid", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:mem0=$NVIDIA_RRD:nvidia_mem0:AVERAGE", + "DEF:mem1=$NVIDIA_RRD:nvidia_mem1:AVERAGE", + "DEF:mem2=$NVIDIA_RRD:nvidia_mem2:AVERAGE", + "DEF:mem3=$NVIDIA_RRD:nvidia_mem3:AVERAGE", + "DEF:mem4=$NVIDIA_RRD:nvidia_mem4:AVERAGE", + "DEF:mem5=$NVIDIA_RRD:nvidia_mem5:AVERAGE", + "DEF:mem6=$NVIDIA_RRD:nvidia_mem6:AVERAGE", + "DEF:mem7=$NVIDIA_RRD:nvidia_mem7:AVERAGE", + "DEF:mem8=$NVIDIA_RRD:nvidia_mem8:AVERAGE", + "COMMENT: \\n", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG3: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG3z", + "--title=$rgraphs{_nvidia3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Percent", + "--width=$width", + "--height=$height", + "--upper-limit=100", + "--lower-limit=0", + "--rigid", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:mem0=$NVIDIA_RRD:nvidia_mem0:AVERAGE", + "DEF:mem1=$NVIDIA_RRD:nvidia_mem1:AVERAGE", + "DEF:mem2=$NVIDIA_RRD:nvidia_mem2:AVERAGE", + "DEF:mem3=$NVIDIA_RRD:nvidia_mem3:AVERAGE", + "DEF:mem4=$NVIDIA_RRD:nvidia_mem4:AVERAGE", + "DEF:mem5=$NVIDIA_RRD:nvidia_mem5:AVERAGE", + "DEF:mem6=$NVIDIA_RRD:nvidia_mem6:AVERAGE", + "DEF:mem7=$NVIDIA_RRD:nvidia_mem7:AVERAGE", + "DEF:mem8=$NVIDIA_RRD:nvidia_mem8:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG3z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /nvidia3/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; +} + +# DISK graph +# ---------------------------------------------------------------------------- +sub disk { + my ($myself, $title) = @_; + + my $width; + my $height; + my @PNG; + my @PNGz; + my @tmp; + my @tmpz; + my $n; + my $n2; + my $e; + my $e2; + my $str; + my $err; + my @LC = ( + "#FFA500", + "#44EEEE", + "#44EE44", + "#4444EE", + "#448844", + "#EE4444", + "#EE44EE", + "#EEEE44", + ); + + $title = !$silent ? $title : ""; + + if($IFACE_MODE eq "text") { + if($title) { + graph_header($title, 2); + print(" \n"); + print(" \n"); + } + my (undef, undef, undef, $data) = RRDs::fetch("$DISK_RRD", + "--start=-$nwhen$twhen", + "AVERAGE", + "-r $res"); + $err = RRDs::error; + print("ERROR: while fetching $DISK_RRD: $err\n") if $err; + my $line1; + my $line2; + my $line3; + print("
\n");
+		foreach my $i (@DISK_LIST) {
+			for($n = 0; $n < scalar(@$i); $n++) {
+				$str = sprintf(" DISK %d               ", $n + 1);
+				$line1 .= $str;
+				$str = sprintf(" Temp Realloc Pending ", $n + 1);
+				$line2 .= $str;
+				$line3 .=      "----------------------";
+			}
+		}
+		print("     $line1\n");
+		print("Time $line2\n");
+		print("-----$line3\n");
+		my $line;
+		my @row;
+		my $time;
+		my $from;
+		my $to;
+		for($n = 0, $time = $tb; $n < ($tb * $ts); $n++) {
+			$line = @$data[$n];
+			$time = $time - (1 / $ts);
+			printf(" %2d$tc ", $time);
+			$e = 0;
+			foreach my $i (@DISK_LIST) {
+				for($n2 = 0; $n2 < scalar(@$i); $n2++) {
+					$from = ($e * 8 * 3) + ($n2 * 3);
+					$to = $from + 3;
+					my ($temp, $realloc, $pending) = @$line[$from..$to];
+					@row = ($temp, $realloc, $pending);
+					printf(" %4.0f %7.0f %7.0f ", @row);
+				}
+				$e++;
+			}
+			print("\n");
+		}
+		print("    
\n"); + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; + } + + for($n = 0; $n < scalar(@DISK_LIST); $n++) { + for($n2 = 1; $n2 <= 8; $n2++) { + $str = $u . $myself . $n . $n2 . "." . $when . ".png"; + push(@PNG, $str); + unlink("$PNG_DIR" . $str); + if($ENABLE_ZOOM eq "Y") { + $str = $u . $myself . $n . $n2 . "z." . $when . ".png"; + push(@PNGz, $str); + unlink("$PNG_DIR" . $str); + } + } + } + + $e = 0; + foreach my $i (@DISK_LIST) { + if($e) { + print("
\n"); + } + if($title) { + graph_header($title, 2); + } + + undef(@tmp); + undef(@tmpz); + push(@tmp, "COMMENT: \\n"); + for($n = 0; $n < 8; $n++) { + if(@$i[$n]) { + my ($dstr) = (split /\s+/, @$i[$n]); + $str = sprintf("%-20s", $dstr); + push(@tmp, "LINE2:hd" . $n . $LC[$n] . ":$str"); + push(@tmpz, "LINE2:hd" . $n . $LC[$n] . ":$dstr"); + push(@tmp, "GPRINT:hd" . $n . ":LAST: Current\\: %2.0lf"); + push(@tmp, "GPRINT:hd" . $n . ":AVERAGE: Average\\: %2.0lf"); + push(@tmp, "GPRINT:hd" . $n . ":MIN: Min\\: %2.0lf"); + push(@tmp, "GPRINT:hd" . $n . ":MAX: Max\\: %2.0lf\\n"); + } + } + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + if(scalar(@$i) && (scalar(@$i) % 2)) { + push(@tmp, "COMMENT: \\n"); + } + if($title) { + print(" \n"); + print(" \n"); + } + ($width, $height) = split('x', $GRAPH_SIZE{main}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG[$e * 3]", + "--title=$rgraphs{_disk1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Celsius", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:hd0=$DISK_RRD:disk" . $e ."_hd0_temp:AVERAGE", + "DEF:hd1=$DISK_RRD:disk" . $e ."_hd1_temp:AVERAGE", + "DEF:hd2=$DISK_RRD:disk" . $e ."_hd2_temp:AVERAGE", + "DEF:hd3=$DISK_RRD:disk" . $e ."_hd3_temp:AVERAGE", + "DEF:hd4=$DISK_RRD:disk" . $e ."_hd4_temp:AVERAGE", + "DEF:hd5=$DISK_RRD:disk" . $e ."_hd5_temp:AVERAGE", + "DEF:hd6=$DISK_RRD:disk" . $e ."_hd6_temp:AVERAGE", + "DEF:hd7=$DISK_RRD:disk" . $e ."_hd7_temp:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG[$e * 3]: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNGz[$e * 3]", + "--title=$rgraphs{_disk1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Celsius", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:hd0=$DISK_RRD:disk" . $e ."_hd0_temp:AVERAGE", + "DEF:hd1=$DISK_RRD:disk" . $e ."_hd1_temp:AVERAGE", + "DEF:hd2=$DISK_RRD:disk" . $e ."_hd2_temp:AVERAGE", + "DEF:hd3=$DISK_RRD:disk" . $e ."_hd3_temp:AVERAGE", + "DEF:hd4=$DISK_RRD:disk" . $e ."_hd4_temp:AVERAGE", + "DEF:hd5=$DISK_RRD:disk" . $e ."_hd5_temp:AVERAGE", + "DEF:hd6=$DISK_RRD:disk" . $e ."_hd6_temp:AVERAGE", + "DEF:hd7=$DISK_RRD:disk" . $e ."_hd7_temp:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNGz[$e * 3]: $err\n") if $err; + } + $e2 = $e + 1; + if($title || ($silent =~ /imagetag/ && $graph =~ /disk$e2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + if($title) { + print(" \n"); + print(" \n"); + } + + undef(@tmp); + undef(@tmpz); + for($n = 0; $n < 8; $n += 2) { + if(@$i[$n]) { + $str = sprintf("%-17s", substr(@$i[$n], 0, 17)); + push(@tmp, "LINE2:rsc" . $n . $LC[$n] . ":$str"); + push(@tmpz, "LINE2:rsc" . $n . $LC[$n] . ":@$i[$n]\\g"); + } + if(@$i[$n + 1]) { + $str = sprintf("%-17s", substr(@$i[$n + 1], 0, 17)); + push(@tmp, "LINE2:rsc" . ($n + 1) . $LC[$n + 1] . ":$str\\n"); + push(@tmpz, "LINE2:rsc" . ($n + 1) . $LC[$n + 1] . ":@$i[$n + 1]\\g"); + } + } + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG[$e * 3 + 1]", + "--title=$rgraphs{_disk2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Sectors", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:rsc0=$DISK_RRD:disk" . $e . "_hd0_smart1:AVERAGE", + "DEF:rsc1=$DISK_RRD:disk" . $e . "_hd1_smart1:AVERAGE", + "DEF:rsc2=$DISK_RRD:disk" . $e . "_hd2_smart1:AVERAGE", + "DEF:rsc3=$DISK_RRD:disk" . $e . "_hd3_smart1:AVERAGE", + "DEF:rsc4=$DISK_RRD:disk" . $e . "_hd4_smart1:AVERAGE", + "DEF:rsc5=$DISK_RRD:disk" . $e . "_hd5_smart1:AVERAGE", + "DEF:rsc6=$DISK_RRD:disk" . $e . "_hd6_smart1:AVERAGE", + "DEF:rsc7=$DISK_RRD:disk" . $e . "_hd7_smart1:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG[$e * 3 + 1]: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNGz[$e * 3 + 1]", + "--title=$rgraphs{_disk2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Sectors", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:rsc0=$DISK_RRD:disk" . $e . "_hd0_smart1:AVERAGE", + "DEF:rsc1=$DISK_RRD:disk" . $e . "_hd1_smart1:AVERAGE", + "DEF:rsc2=$DISK_RRD:disk" . $e . "_hd2_smart1:AVERAGE", + "DEF:rsc3=$DISK_RRD:disk" . $e . "_hd3_smart1:AVERAGE", + "DEF:rsc4=$DISK_RRD:disk" . $e . "_hd4_smart1:AVERAGE", + "DEF:rsc5=$DISK_RRD:disk" . $e . "_hd5_smart1:AVERAGE", + "DEF:rsc6=$DISK_RRD:disk" . $e . "_hd6_smart1:AVERAGE", + "DEF:rsc7=$DISK_RRD:disk" . $e . "_hd7_smart1:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNGz[$e * 3 + 1]: $err\n") if $err; + } + $e2 = $e + 2; + if($title || ($silent =~ /imagetag/ && $graph =~ /disk$e2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@tmp); + undef(@tmpz); + for($n = 0; $n < 8; $n += 2) { + if(@$i[$n]) { + $str = sprintf("%-17s", substr(@$i[$n], 0, 17)); + push(@tmp, "LINE2:cps" . $n . $LC[$n] . ":$str"); + push(@tmpz, "LINE2:cps" . $n . $LC[$n] . ":@$i[$n]\\g"); + } + if(@$i[$n + 1]) { + $str = sprintf("%-17s", substr(@$i[$n + 1], 0, 17)); + push(@tmp, "LINE2:cps" . ($n + 1) . $LC[$n + 1] . ":$str\\n"); + push(@tmpz, "LINE2:cps" . ($n + 1) . $LC[$n + 1] . ":@$i[$n + 1]\\g"); + } + } + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG[$e * 3 + 2]", + "--title=$rgraphs{_disk3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Sectors", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:cps0=$DISK_RRD:disk" . $e . "_hd0_smart2:AVERAGE", + "DEF:cps1=$DISK_RRD:disk" . $e . "_hd1_smart2:AVERAGE", + "DEF:cps2=$DISK_RRD:disk" . $e . "_hd2_smart2:AVERAGE", + "DEF:cps3=$DISK_RRD:disk" . $e . "_hd3_smart2:AVERAGE", + "DEF:cps4=$DISK_RRD:disk" . $e . "_hd4_smart2:AVERAGE", + "DEF:cps5=$DISK_RRD:disk" . $e . "_hd5_smart2:AVERAGE", + "DEF:cps6=$DISK_RRD:disk" . $e . "_hd6_smart2:AVERAGE", + "DEF:cps7=$DISK_RRD:disk" . $e . "_hd7_smart2:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG[$e * 3 + 2]: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNGz[$e * 3 + 2]", + "--title=$rgraphs{_disk3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Sectors", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:cps0=$DISK_RRD:disk" . $e . "_hd0_smart2:AVERAGE", + "DEF:cps1=$DISK_RRD:disk" . $e . "_hd1_smart2:AVERAGE", + "DEF:cps2=$DISK_RRD:disk" . $e . "_hd2_smart2:AVERAGE", + "DEF:cps3=$DISK_RRD:disk" . $e . "_hd3_smart2:AVERAGE", + "DEF:cps4=$DISK_RRD:disk" . $e . "_hd4_smart2:AVERAGE", + "DEF:cps5=$DISK_RRD:disk" . $e . "_hd5_smart2:AVERAGE", + "DEF:cps6=$DISK_RRD:disk" . $e . "_hd6_smart2:AVERAGE", + "DEF:cps7=$DISK_RRD:disk" . $e . "_hd7_smart2:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNGz[$e * 3 + 2]: $err\n") if $err; + } + $e2 = $e + 3; + if($title || ($silent =~ /imagetag/ && $graph =~ /disk$e2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + $e++; + } + return 1; +} + +# FS graph +# ---------------------------------------------------------------------------- +sub fs { + my ($myself, $title) = @_; + + my $width; + my $height; + my $graph_title; + my $vlabel; + my @PNG; + my @PNGz; + my @tmp; + my @tmpz; + my @riglim; + my $n; + my $n2; + my $e; + my $e2; + my $str; + my $err; + my @LC = ( + "#FFA500", + "#44EEEE", + "#44EE44", + "#4444EE", + "#448844", + "#5F04B4", + "#EE44EE", + "#EEEE44", + ); + + $title = !$silent ? $title : ""; + + if($IFACE_MODE eq "text") { + if($title) { + graph_header($title, 2); + print(" \n"); + print(" \n"); + } + my (undef, undef, undef, $data) = RRDs::fetch("$FS_RRD", + "--start=-$nwhen$twhen", + "AVERAGE", + "-r $res"); + $err = RRDs::error; + print("ERROR: while fetching $FS_RRD: $err\n") if $err; + my $line1; + my $line2; + my $line3; + print("
\n");
+		foreach my $i (@FS_LIST) {
+			for($n = 0; $n < scalar(@$i); $n++) {
+				$str = sprintf("%23s", @$i[$n]);
+				$line1 .= $str;
+				$str = sprintf("   Use     I/O    Time ");
+				$line2 .= $str;
+				$line3 .=      "-----------------------";
+			}
+		}
+		print("    $line1\n");
+		print("Time $line2\n");
+		print("-----$line3\n");
+		my $line;
+		my @row;
+		my $time;
+		my $from;
+		my $to;
+		for($n = 0, $time = $tb; $n < ($tb * $ts); $n++) {
+			$line = @$data[$n];
+			$time = $time - (1 / $ts);
+			my ($root, $swap) = @$line;
+			printf(" %2d$tc ", $time);
+			$e = 0;
+			foreach my $i (@FS_LIST) {
+				for($n2 = 0; $n2 < scalar(@$i); $n2++) {
+					$from = ($e * 8 * 3) + ($n2 * 3);
+					$to = $from + 3;
+					my ($use, $ioa, $tim) = @$line[$from..$to];
+					@row = ($use, $ioa, $tim);
+					printf(" %4.1f%% %7.1f %7.1f ", @row);
+				}
+				$e++;
+			}
+			print("\n");
+		}
+		print("    
\n"); + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; + } + + for($n = 0; $n < scalar(@FS_LIST); $n++) { + for($n2 = 1; $n2 <= 8; $n2++) { + $str = $u . $myself . $n . $n2 . "." . $when . ".png"; + push(@PNG, $str); + unlink("$PNG_DIR" . $str); + if($ENABLE_ZOOM eq "Y") { + $str = $u . $myself . $n . $n2 . "z." . $when . ".png"; + push(@PNGz, $str); + unlink("$PNG_DIR" . $str); + } + } + } + + $e = 0; + foreach my $i (@FS_LIST) { + if($e) { + print("
\n"); + } + if($title) { + graph_header($title, 2); + } + + undef(@tmp); + undef(@tmpz); + push(@tmp, "COMMENT: \\n"); + for($n = 0; $n < 8; $n++) { + if(@$i[$n]) { + my $color; + + $str = $FS_DESC{@$i[$n]}; + $str = @$i[$n] unless $str; + if($str eq "/") { + $color = "#EE4444"; + } elsif($str eq "swap") { + $color = "#CCCCCC"; + } elsif($str eq "/boot") { + $color = "#666666"; + } else { + $color = $LC[$n]; + } + push(@tmpz, "LINE2:fs" . $n . $color . ":$str"); + $str = sprintf("%-23s", $str); + push(@tmp, "LINE2:fs" . $n . $color . ":$str"); + push(@tmp, "GPRINT:fs" . $n . ":LAST:Cur\\: %4.1lf%%"); + push(@tmp, "GPRINT:fs" . $n . ":AVERAGE: Avg\\: %4.1lf%%"); + push(@tmp, "GPRINT:fs" . $n . ":MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:fs" . $n . ":MAX: Max\\: %4.1lf%%\\n"); + } + } + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + if(scalar(@$i) && (scalar(@$i) % 2)) { + push(@tmp, "COMMENT: \\n"); + } + if($title) { + print(" \n"); + print(" \n"); + } + ($width, $height) = split('x', $GRAPH_SIZE{main}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@line, "COMMENT: \\n"); + push(@line, "COMMENT: \\n"); + push(@line, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG[$e * 3]", + "--title=$rgraphs{_fs1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Percent (%)", + "--width=$width", + "--height=$height", + "--upper-limit=100", + "--lower-limit=0", + "--rigid", + @VERSION12, + @graph_colors, + "DEF:fs0=$FS_RRD:fs" . $e . "_use0:AVERAGE", + "DEF:fs1=$FS_RRD:fs" . $e . "_use1:AVERAGE", + "DEF:fs2=$FS_RRD:fs" . $e . "_use2:AVERAGE", + "DEF:fs3=$FS_RRD:fs" . $e . "_use3:AVERAGE", + "DEF:fs4=$FS_RRD:fs" . $e . "_use4:AVERAGE", + "DEF:fs5=$FS_RRD:fs" . $e . "_use5:AVERAGE", + "DEF:fs6=$FS_RRD:fs" . $e . "_use6:AVERAGE", + "DEF:fs7=$FS_RRD:fs" . $e . "_use7:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG[$e * 3]: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNGz[$e * 3]", + "--title=$rgraphs{_fs1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Percent (%)", + "--width=$width", + "--height=$height", + "--upper-limit=100", + "--lower-limit=0", + "--rigid", + @VERSION12, + @graph_colors, + "DEF:fs0=$FS_RRD:fs" . $e . "_use0:AVERAGE", + "DEF:fs1=$FS_RRD:fs" . $e . "_use1:AVERAGE", + "DEF:fs2=$FS_RRD:fs" . $e . "_use2:AVERAGE", + "DEF:fs3=$FS_RRD:fs" . $e . "_use3:AVERAGE", + "DEF:fs4=$FS_RRD:fs" . $e . "_use4:AVERAGE", + "DEF:fs5=$FS_RRD:fs" . $e . "_use5:AVERAGE", + "DEF:fs6=$FS_RRD:fs" . $e . "_use6:AVERAGE", + "DEF:fs7=$FS_RRD:fs" . $e . "_use7:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNGz[$e * 3]: $err\n") if $err; + } + $e2 = $e + 1; + if($title || ($silent =~ /imagetag/ && $graph =~ /fs$e2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + if($title) { + print(" \n"); + print(" \n"); + } + + undef(@riglim); + if($FS2_RIGID eq 1) { + push(@riglim, "--upper-limit=$FS2_LIMIT"); + } else { + if($FS2_RIGID eq 2) { + push(@riglim, "--upper-limit=$FS2_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + for($n = 0; $n < 8; $n += 2) { + my $color; + if(@$i[$n]) { + $str = $FS_DESC{@$i[$n]}; + $str = @$i[$n] unless $str; + if($str eq "/") { + $color = "#EE4444"; + } elsif($str eq "swap") { + $color = "#CCCCCC"; + } elsif($str eq "/boot") { + $color = "#666666"; + } else { + $color = $LC[$n]; + } + push(@tmpz, "LINE2:ioa" . $n . $color . ":$str\\g"); + $str = sprintf("%-17s", substr($str, 0, 17)); + push(@tmp, "LINE2:ioa" . $n . $color . ":$str"); + } + if(@$i[$n + 1]) { + $str = $FS_DESC{@$i[$n + 1]}; + $str = @$i[$n + 1] unless $str; + if($str eq "/") { + $color = "#EE4444"; + } elsif($str eq "swap") { + $color = "#CCCCCC"; + } elsif($str eq "/boot") { + $color = "#666666"; + } else { + $color = $LC[$n + 1]; + } + push(@tmpz, "LINE2:ioa" . ($n + 1) . $color . ":$str\\g"); + $str = sprintf("%-17s", substr($str, 0, 17)); + push(@tmp, "LINE2:ioa" . ($n + 1) . $color . ":$str\\n"); + } + } + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG[$e * 3 + 1]", + "--title=$rgraphs{_fs2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Reads+Writes/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:ioa0=$FS_RRD:fs" . $e . "_ioa0:AVERAGE", + "DEF:ioa1=$FS_RRD:fs" . $e . "_ioa1:AVERAGE", + "DEF:ioa2=$FS_RRD:fs" . $e . "_ioa2:AVERAGE", + "DEF:ioa3=$FS_RRD:fs" . $e . "_ioa3:AVERAGE", + "DEF:ioa4=$FS_RRD:fs" . $e . "_ioa4:AVERAGE", + "DEF:ioa5=$FS_RRD:fs" . $e . "_ioa5:AVERAGE", + "DEF:ioa6=$FS_RRD:fs" . $e . "_ioa6:AVERAGE", + "DEF:ioa7=$FS_RRD:fs" . $e . "_ioa7:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG[$e * 3 + 1]: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNGz[$e * 3 + 1]", + "--title=$rgraphs{_fs2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Reads+Writes/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:ioa0=$FS_RRD:fs" . $e . "_ioa0:AVERAGE", + "DEF:ioa1=$FS_RRD:fs" . $e . "_ioa1:AVERAGE", + "DEF:ioa2=$FS_RRD:fs" . $e . "_ioa2:AVERAGE", + "DEF:ioa3=$FS_RRD:fs" . $e . "_ioa3:AVERAGE", + "DEF:ioa4=$FS_RRD:fs" . $e . "_ioa4:AVERAGE", + "DEF:ioa5=$FS_RRD:fs" . $e . "_ioa5:AVERAGE", + "DEF:ioa6=$FS_RRD:fs" . $e . "_ioa6:AVERAGE", + "DEF:ioa7=$FS_RRD:fs" . $e . "_ioa7:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNGz[$e * 3 + 1]: $err\n") if $err; + } + $e2 = $e + 2; + if($title || ($silent =~ /imagetag/ && $graph =~ /fs$e2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@riglim); + if($FS3_RIGID eq 1) { + push(@riglim, "--upper-limit=$FS3_LIMIT"); + } else { + if($FS3_RIGID eq 2) { + push(@riglim, "--upper-limit=$FS3_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + if($os eq "Linux") { + if($kernel_branch > 2.4) { + $graph_title = "$rgraphs{_fs3} ($nwhen$twhen)"; + $vlabel = "Milliseconds"; + } else { + $graph_title = "Disk sectors activity ($nwhen$twhen)"; + $vlabel = "Sectors/s"; + } + for($n = 0; $n < 8; $n += 2) { + my $color; + if(@$i[$n]) { + $str = $FS_DESC{@$i[$n]}; + $str = @$i[$n] unless $str; + if($str eq "/") { + $color = "#EE4444"; + } elsif($str eq "swap") { + $color = "#CCCCCC"; + } elsif($str eq "/boot") { + $color = "#666666"; + } else { + $color = $LC[$n]; + } + push(@tmpz, "LINE2:tim" . $n . $color . ":$str\\g"); + $str = sprintf("%-17s", substr($str, 0, 17)); + push(@tmp, "LINE2:tim" . $n . $color . ":$str"); + } + if(@$i[$n + 1]) { + $str = $FS_DESC{@$i[$n + 1]}; + $str = @$i[$n + 1] unless $str; + if($str eq "/") { + $color = "#EE4444"; + } elsif($str eq "swap") { + $color = "#CCCCCC"; + } elsif($str eq "/boot") { + $color = "#666666"; + } else { + $color = $LC[$n + 1]; + } + push(@tmpz, "LINE2:tim" . ($n + 1) . $color . ":$str\\g"); + $str = sprintf("%-17s", substr($str, 0, 17)); + push(@tmp, "LINE2:tim" . ($n + 1) . $color . ":$str\\n"); + } + } + } elsif(grep {$_ eq $os} ("FreeBSD", "OpenBSD", "NetBSD")) { + $graph_title = "Disk data activity ($nwhen$twhen)"; + $vlabel = "KB/s"; + for($n = 0; $n < 8; $n += 2) { + my $color; + if(@$i[$n]) { + $str = sprintf("%-17s", substr(@$i[$n], 0, 17)); + if($str eq "/") { + $color = "#EE4444"; + } elsif($str eq "swap") { + $color = "#CCCCCC"; + } elsif($str eq "/boot") { + $color = "#666666"; + } else { + $color = $LC[$n]; + } + push(@tmp, "LINE2:tim" . $n . $color . ":$str"); + push(@tmpz, "LINE2:tim" . $n . $color . ":@$i[$n]\\g"); + } + if(@$i[$n + 1]) { + $str = sprintf("%-17s", substr(@$i[$n + 1], 0, 17)); + if($str eq "/") { + $color = "#EE4444"; + } elsif($str eq "swap") { + $color = "#CCCCCC"; + } elsif($str eq "/boot") { + $color = "#666666"; + } else { + $color = $LC[$n + 1]; + } + push(@tmp, "LINE2:tim" . ($n + 1) . $color . ":$str\\n"); + push(@tmpz, "LINE2:tim" . ($n + 1) . $color . ":@$i[$n + 1]\\g"); + } + } + } + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG[$e * 3 + 2]", + "--title=$graph_title", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=$vlabel", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:tim0=$FS_RRD:fs" . $e . "_tim0:AVERAGE", + "DEF:tim1=$FS_RRD:fs" . $e . "_tim1:AVERAGE", + "DEF:tim2=$FS_RRD:fs" . $e . "_tim2:AVERAGE", + "DEF:tim3=$FS_RRD:fs" . $e . "_tim3:AVERAGE", + "DEF:tim4=$FS_RRD:fs" . $e . "_tim4:AVERAGE", + "DEF:tim5=$FS_RRD:fs" . $e . "_tim5:AVERAGE", + "DEF:tim6=$FS_RRD:fs" . $e . "_tim6:AVERAGE", + "DEF:tim7=$FS_RRD:fs" . $e . "_tim7:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG[$e * 3 + 2]: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNGz[$e * 3 + 2]", + "--title=$graph_title", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=$vlabel", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:tim0=$FS_RRD:fs" . $e . "_tim0:AVERAGE", + "DEF:tim1=$FS_RRD:fs" . $e . "_tim1:AVERAGE", + "DEF:tim2=$FS_RRD:fs" . $e . "_tim2:AVERAGE", + "DEF:tim3=$FS_RRD:fs" . $e . "_tim3:AVERAGE", + "DEF:tim4=$FS_RRD:fs" . $e . "_tim4:AVERAGE", + "DEF:tim5=$FS_RRD:fs" . $e . "_tim5:AVERAGE", + "DEF:tim6=$FS_RRD:fs" . $e . "_tim6:AVERAGE", + "DEF:tim7=$FS_RRD:fs" . $e . "_tim7:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNGz[$e * 3 + 2]: $err\n") if $err; + } + $e2 = $e + 3; + if($title || ($silent =~ /imagetag/ && $graph =~ /fs$e2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + $e++; + } + return 1; +} + +# NET graph +# ---------------------------------------------------------------------------- +sub net { + my ($myself, $title) = @_; + + my $width; + my $height; + my @riglim; + my $PNG1; + my $PNG2; + my $PNG3; + my $PNG1z; + my $PNG2z; + my $PNG3z; + my $netname; + my @tmp; + my @tmpz; + my @CDEF; + my $T = "B"; + my $vlabel = "bytes/s"; + my $n; + my $str; + my $err; + + $title = !$silent ? $title : ""; + + if($NETSTATS_IN_BPS eq "Y") { + $T = "b"; + $vlabel = "bits/s"; + } + if($IFACE_MODE eq "text") { + if($title) { + graph_header($title, 2); + print(" \n"); + print(" \n"); + } + my (undef, undef, undef, $data) = RRDs::fetch("$NET_RRD", + "--start=-$nwhen$twhen", + "AVERAGE", + "-r $res"); + $err = RRDs::error; + print("ERROR: while fetching $NET_RRD: $err\n") if $err; + print("
\n");
+		print("       ");
+		for($n = 0; $n < scalar(@NET_LIST); $n++) {
+			print("$NET_LIST[$n] ($NET_DESC[$n])                          ");
+		}
+		print("\nTime");
+		for($n = 0; $n < scalar(@NET_LIST); $n++) {
+			print("   K$T/s_I  K$T/s_O  Pk/s_I  Pk/s_O  Er/s_I  Er/s_O");
+		}
+		print(" \n----");
+		for($n = 0; $n < scalar(@NET_LIST); $n++) {
+			print("-------------------------------------------------");
+		}
+		print " \n";
+		my $line;
+		my @row;
+		my $time;
+		my $n2;
+		my $from;
+		my $to;
+		for($n = 0, $time = $tb; $n < ($tb * $ts); $n++) {
+			$line = @$data[$n];
+			$time = $time - (1 / $ts);
+			printf(" %2d$tc", $time);
+			for($n2 = 0; $n2 < scalar(@NET_LIST); $n2++) {
+				$from = $n2 * 6;
+				$to = $from + 6;
+				my ($ki, $ko, $pi, $po, $ei, $eo) = @$line[$from..$to];
+				$ki /= 1024;
+				$ko /= 1024;
+				$pi /= 1024;
+				$po /= 1024;
+				$ei /= 1024;
+				$eo /= 1024;
+				if($NETSTATS_IN_BPS eq "Y") {
+					$ki *= 8;
+					$ko *= 8;
+				}
+				@row = ($ki, $ko, $pi, $po, $ei, $eo);
+				printf("   %6d  %6d  %6d  %6d  %6d  %6d", @row);
+			}
+			print(" \n");
+		}
+		print("    
\n"); + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; + } + + for($n = 0; $n < scalar(@NET_LIST); $n++) { + $PNG1 = $u . $myself . $n . "1." . $when . ".png"; + $PNG2 = $u . $myself . $n . "2." . $when . ".png"; + $PNG3 = $u . $myself . $n . "3." . $when . ".png"; + unlink("$PNG_DIR" . $PNG1); + unlink("$PNG_DIR" . $PNG2); + unlink("$PNG_DIR" . $PNG3); + if($ENABLE_ZOOM eq "Y") { + $PNG1z = $u . $myself . $n . "1z." . $when . ".png"; + $PNG2z = $u . $myself . $n . "2z." . $when . ".png"; + $PNG3z = $u . $myself . $n . "3z." . $when . ".png"; + unlink("$PNG_DIR" . $PNG1z); + unlink("$PNG_DIR" . $PNG2z); + unlink("$PNG_DIR" . $PNG3z); + } + + if($title) { + if($n) { + print("
\n"); + } + graph_header($NET_LIST[$n] . " " . $title, 2); + print(" \n"); + print(" \n"); + } + + undef(@riglim); + if($NET_RIGID[$n] eq 1) { + push(@riglim, "--upper-limit=$NET_LIMIT[$n]"); + } else { + if($NET_RIGID[$n] eq 2) { + push(@riglim, "--upper-limit=$NET_LIMIT[$n]"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + undef(@CDEF); + push(@tmp, "AREA:B_in#44EE44:K$T/s Input"); + push(@tmp, "GPRINT:K_in:LAST: Current\\: %5.0lf"); + push(@tmp, "GPRINT:K_in:AVERAGE: Average\\: %5.0lf"); + push(@tmp, "GPRINT:K_in:MIN: Min\\: %5.0lf"); + push(@tmp, "GPRINT:K_in:MAX: Max\\: %5.0lf\\n"); + push(@tmp, "AREA:B_out#4444EE:K$T/s Output"); + push(@tmp, "GPRINT:K_out:LAST: Current\\: %5.0lf"); + push(@tmp, "GPRINT:K_out:AVERAGE: Average\\: %5.0lf"); + push(@tmp, "GPRINT:K_out:MIN: Min\\: %5.0lf"); + push(@tmp, "GPRINT:K_out:MAX: Max\\: %5.0lf\\n"); + push(@tmp, "AREA:B_out#4444EE:"); + push(@tmp, "AREA:B_in#44EE44:"); + push(@tmp, "LINE1:B_out#0000EE"); + push(@tmp, "LINE1:B_in#00EE00"); + push(@tmpz, "AREA:B_in#44EE44:Input"); + push(@tmpz, "AREA:B_out#4444EE:Output"); + push(@tmpz, "AREA:B_out#4444EE:"); + push(@tmpz, "AREA:B_in#44EE44:"); + push(@tmpz, "LINE1:B_out#0000EE"); + push(@tmpz, "LINE1:B_in#00EE00"); + if($NETSTATS_IN_BPS eq "Y") { + push(@CDEF, "CDEF:B_in=in,8,*"); + push(@CDEF, "CDEF:B_out=out,8,*"); + } else { + push(@CDEF, "CDEF:B_in=in"); + push(@CDEF, "CDEF:B_out=out"); + } + ($width, $height) = split('x', $GRAPH_SIZE{main}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG1", + "--title=$NET_LIST[$n] $NET_DESC[$n] $rgraphs{_net1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=$vlabel", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:in=$NET_RRD:net" . $n . "_bytes_in:AVERAGE", + "DEF:out=$NET_RRD:net" . $n . "_bytes_out:AVERAGE", + @CDEF, + "CDEF:K_in=B_in,1024,/", + "CDEF:K_out=B_out,1024,/", + "COMMENT: \\n", + @tmp, + "COMMENT: \\n", + "COMMENT: \\n", + ); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG1: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG1z", + "--title=$NET_LIST[$n] $NET_DESC[$n] $rgraphs{_net1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=$vlabel", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:in=$NET_RRD:net" . $n . "_bytes_in:AVERAGE", + "DEF:out=$NET_RRD:net" . $n . "_bytes_out:AVERAGE", + @CDEF, + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG1z: $err\n") if $err; + } + $netname="net" . $n . "1"; + if($title || ($silent =~ /imagetag/ && $graph =~ /$netname/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + if($title) { + print(" \n"); + print(" \n"); + } + + undef(@tmp); + undef(@tmpz); + push(@tmp, "AREA:p_in#44EE44:Input"); + push(@tmp, "AREA:p_out#4444EE:Output"); + push(@tmp, "AREA:p_out#4444EE:"); + push(@tmp, "AREA:p_in#44EE44:"); + push(@tmp, "LINE1:p_out#0000EE"); + push(@tmp, "LINE1:p_in#00EE00"); + push(@tmpz, "AREA:p_in#44EE44:Input"); + push(@tmpz, "AREA:p_out#4444EE:Output"); + push(@tmpz, "AREA:p_out#4444EE:"); + push(@tmpz, "AREA:p_in#44EE44:"); + push(@tmpz, "LINE1:p_out#0000EE"); + push(@tmpz, "LINE1:p_in#00EE00"); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG2", + "--title=$NET_LIST[$n] $rgraphs{_net2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Packets/s", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:p_in=$NET_RRD:net" . $n . "_packs_in:AVERAGE", + "DEF:p_out=$NET_RRD:net" . $n . "_packs_out:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG2: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG2z", + "--title=$NET_LIST[$n] $rgraphs{_net2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Packets/s", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:p_in=$NET_RRD:net" . $n . "_packs_in:AVERAGE", + "DEF:p_out=$NET_RRD:net" . $n . "_packs_out:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG2z: $err\n") if $err; + } + $netname="net" . $n . "2"; + if($title || ($silent =~ /imagetag/ && $graph =~ /$netname/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@tmp); + undef(@tmpz); + push(@tmp, "AREA:e_in#44EE44:Input"); + push(@tmp, "AREA:e_out#4444EE:Output"); + push(@tmp, "AREA:e_out#4444EE:"); + push(@tmp, "AREA:e_in#44EE44:"); + push(@tmp, "LINE1:e_out#0000EE"); + push(@tmp, "LINE1:e_in#00EE00"); + push(@tmpz, "AREA:e_in#44EE44:Input"); + push(@tmpz, "AREA:e_out#4444EE:Output"); + push(@tmpz, "AREA:e_out#4444EE:"); + push(@tmpz, "AREA:e_in#44EE44:"); + push(@tmpz, "LINE1:e_out#0000EE"); + push(@tmpz, "LINE1:e_in#00EE00"); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG3", + "--title=$NET_LIST[$n] $rgraphs{_net3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Errors/s", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:e_in=$NET_RRD:net" . $n . "_error_in:AVERAGE", + "DEF:e_out=$NET_RRD:net" . $n . "_error_out:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG3: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG3z", + "--title=$NET_LIST[$n] $rgraphs{_net3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Errors/s", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:e_in=$NET_RRD:net" . $n . "_error_in:AVERAGE", + "DEF:e_out=$NET_RRD:net" . $n . "_error_out:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG3z: $err\n") if $err; + } + $netname="net" . $n . "3"; + if($title || ($silent =~ /imagetag/ && $graph =~ /$netname/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + } + return 1; +} + +# SERV graph +# ---------------------------------------------------------------------------- +sub serv { + my ($myself, $title) = @_; + + my $width; + my $height; + my $vlabel; + my @tmp; + my @tmpz; + my $n; + my $str; + my $err; + + my $PNG1 = $u . $myself . "1." . $when . ".png"; + my $PNG2 = $u . $myself . "2." . $when . ".png"; + my $PNG3 = $u . $myself . "3." . $when . ".png"; + my $PNG1z = $u . $myself . "1z." . $when . ".png"; + my $PNG2z = $u . $myself . "2z." . $when . ".png"; + my $PNG3z = $u . $myself . "3z." . $when . ".png"; + + $title = !$silent ? $title : ""; + + unlink ("$PNG_DIR" . "$PNG1", + "$PNG_DIR" . "$PNG2", + "$PNG_DIR" . "$PNG3"); + if($ENABLE_ZOOM eq "Y") { + unlink ("$PNG_DIR" . "$PNG1z", + "$PNG_DIR" . "$PNG2z", + "$PNG_DIR" . "$PNG3z"); + } + + if($IFACE_MODE eq "text") { + if($title) { + graph_header($title, 2); + print(" \n"); + print(" \n"); + } + my (undef, undef, undef, $data) = RRDs::fetch("$SERV_RRD", + "--start=-$nwhen$twhen", + "AVERAGE", + "-r $res"); + $err = RRDs::error; + print("ERROR: while fetching $SERV_RRD: $err\n") if $err; + print("
\n");
+		if($SERV_MODE eq "I") {
+			print "Values expressed as incremental or cumulative hits.\n";
+		}
+		print("Time    SSH     FTP  Telnet   Samba     Fax    CUPS     F2B    IMAP    POP3    SMTP    Spam   Virus\n");
+		print("--------------------------------------------------------------------------------------------------- \n");
+		my $line;
+		my @row;
+		my $time;
+		my $from = 0;
+		my $to;
+		if($SERV_MODE eq "L") {
+			$from = 15;
+		}
+		for($n = 0, $time = $tb; $n < ($tb * $ts); $n++) {
+			$line = @$data[$n];
+			$time = $time - (1 / $ts);
+			$to = $from + 10;
+			my ($ssh, $ftp, $telnet, $imap, $smb, $fax, $cups, $pop3, $smtp, $spam, $virus, $f2b) = @$line[$from..$to];
+			@row = ($ssh, $ftp, $telnet, $imap, $smb, $fax, $cups, $f2b, $pop3, $smtp, $spam, $virus);
+			if($SERV_MODE eq "I") {
+				printf(" %2d$tc %6d  %6d  %6d  %6d  %6d  %6d  %6d  %6d  %6d  %6d  %6d  %6d\n", $time, @row);
+			} elsif($SERV_MODE eq "L") {
+				printf(" %2d$tc %6.2f  %6.2f  %6.2f  %6.2f  %6.2f  %6.2f  %6.2f  %6.2f  %6.2f  %6.2f  %6.2f  %6.2f\n", $time, @row);
+			}
+		}
+		print("    
\n"); + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; + } + + if($title) { + graph_header($title, 2); + } + if($SERV_MODE eq "L") { + $vlabel = "Accesses/s"; + push(@tmp, "AREA:l_ssh#4444EE:SSH"); + push(@tmp, "GPRINT:l_ssh:LAST: Current\\: %3.2lf"); + push(@tmp, "GPRINT:l_ssh:AVERAGE: Average\\: %3.2lf"); + push(@tmp, "GPRINT:l_ssh:MIN: Min\\: %3.2lf"); + push(@tmp, "GPRINT:l_ssh:MAX: Max\\: %3.2lf\\n"); + push(@tmp, "AREA:l_ftp#44EE44:FTP"); + push(@tmp, "GPRINT:l_ftp:LAST: Current\\: %3.2lf"); + push(@tmp, "GPRINT:l_ftp:AVERAGE: Average\\: %3.2lf"); + push(@tmp, "GPRINT:l_ftp:MIN: Min\\: %3.2lf"); + push(@tmp, "GPRINT:l_ftp:MAX: Max\\: %3.2lf\\n"); + push(@tmp, "AREA:l_telnet#EE44EE:Telnet"); + push(@tmp, "GPRINT:l_telnet:LAST: Current\\: %3.2lf"); + push(@tmp, "GPRINT:l_telnet:AVERAGE: Average\\: %3.2lf"); + push(@tmp, "GPRINT:l_telnet:MIN: Min\\: %3.2lf"); + push(@tmp, "GPRINT:l_telnet:MAX: Max\\: %3.2lf\\n"); +# push(@tmp, "AREA:l_imap#44EEEE:IMAP"); +# push(@tmp, "GPRINT:l_imap:LAST: Current\\: %3.2lf"); +# push(@tmp, "GPRINT:l_imap:AVERAGE: Average\\: %3.2lf"); +# push(@tmp, "GPRINT:l_imap:MIN: Min\\: %3.2lf"); +# push(@tmp, "GPRINT:l_imap:MAX: Max\\: %3.2lf\\n"); + push(@tmp, "AREA:l_smb#EEEE44:Samba"); + push(@tmp, "GPRINT:l_smb:LAST: Current\\: %3.2lf"); + push(@tmp, "GPRINT:l_smb:AVERAGE: Average\\: %3.2lf"); + push(@tmp, "GPRINT:l_smb:MIN: Min\\: %3.2lf"); + push(@tmp, "GPRINT:l_smb:MAX: Max\\: %3.2lf\\n"); + push(@tmp, "AREA:l_fax#FFA500:Fax"); + push(@tmp, "GPRINT:l_fax:LAST: Current\\: %3.2lf"); + push(@tmp, "GPRINT:l_fax:AVERAGE: Average\\: %3.2lf"); + push(@tmp, "GPRINT:l_fax:MIN: Min\\: %3.2lf"); + push(@tmp, "GPRINT:l_fax:MAX: Max\\: %3.2lf\\n"); + push(@tmp, "AREA:l_cups#444444:CUPS"); + push(@tmp, "GPRINT:l_cups:LAST: Current\\: %3.2lf"); + push(@tmp, "GPRINT:l_cups:AVERAGE: Average\\: %3.2lf"); + push(@tmp, "GPRINT:l_cups:MIN: Min\\: %3.2lf"); + push(@tmp, "GPRINT:l_cups:MAX: Max\\: %3.2lf\\n"); + push(@tmp, "AREA:l_f2b#EE4444:Fail2ban"); + push(@tmp, "GPRINT:l_f2b:LAST: Current\\: %3.2lf"); + push(@tmp, "GPRINT:l_f2b:AVERAGE: Average\\: %3.2lf"); + push(@tmp, "GPRINT:l_f2b:MIN: Min\\: %3.2lf"); + push(@tmp, "GPRINT:l_f2b:MAX: Max\\: %3.2lf\\n"); + push(@tmp, "LINE2:l_ssh#4444EE"); + push(@tmp, "LINE2:l_ftp#44EE44"); + push(@tmp, "LINE2:l_telnet#EE44EE"); +# push(@tmp, "LINE2:l_imap#44EEEE"); + push(@tmp, "LINE2:l_smb#EEEE44"); + push(@tmp, "LINE2:l_fax#FFA500"); + push(@tmp, "LINE2:l_cups#444444"); + push(@tmp, "LINE2:l_f2b#EE4444"); + push(@tmp, "COMMENT: \\n"); + + push(@tmpz, "AREA:l_ssh#4444EE:SSH"); + push(@tmpz, "AREA:l_ftp#44EE44:FTP"); + push(@tmpz, "AREA:l_telnet#EE44EE:Telnet"); +# push(@tmpz, "AREA:l_imap#44EEEE:IMAP"); + push(@tmpz, "AREA:l_smb#EEEE44:Samba"); + push(@tmpz, "AREA:l_fax#FFA500:Fax"); + push(@tmpz, "AREA:l_cups#444444:CUPS"); + push(@tmpz, "AREA:l_f2b#EE4444:Fail2ban"); + push(@tmpz, "LINE2:l_ssh#4444EE"); + push(@tmpz, "LINE2:l_ftp#44EE44"); + push(@tmpz, "LINE2:l_telnet#EE44EE"); +# push(@tmpz, "LINE2:l_imap#44EEEE"); + push(@tmpz, "LINE2:l_smb#EEEE44"); + push(@tmpz, "LINE2:l_fax#FFA500"); + push(@tmpz, "LINE2:l_cups#444444"); + push(@tmpz, "LINE2:l_f2b#EE4444"); + } else { + $vlabel = "Incremental hits"; + push(@tmp, "AREA:i_ssh#4444EE:SSH"); + push(@tmp, "GPRINT:i_ssh:LAST: Current\\: %5.0lf"); + push(@tmp, "GPRINT:i_ssh:AVERAGE: Average\\: %5.0lf"); + push(@tmp, "GPRINT:i_ssh:MIN: Min\\: %5.0lf"); + push(@tmp, "GPRINT:i_ssh:MAX: Max\\: %5.0lf\\n"); + push(@tmp, "AREA:i_ftp#44EE44:FTP"); + push(@tmp, "GPRINT:i_ftp:LAST: Current\\: %5.0lf"); + push(@tmp, "GPRINT:i_ftp:AVERAGE: Average\\: %5.0lf"); + push(@tmp, "GPRINT:i_ftp:MIN: Min\\: %5.0lf"); + push(@tmp, "GPRINT:i_ftp:MAX: Max\\: %5.0lf\\n"); + push(@tmp, "AREA:i_telnet#EE44EE:Telnet"); + push(@tmp, "GPRINT:i_telnet:LAST: Current\\: %5.0lf"); + push(@tmp, "GPRINT:i_telnet:AVERAGE: Average\\: %5.0lf"); + push(@tmp, "GPRINT:i_telnet:MIN: Min\\: %5.0lf"); + push(@tmp, "GPRINT:i_telnet:MAX: Max\\: %5.0lf\\n"); +# push(@tmp, "AREA:i_imap#44EEEE:IMAP"); +# push(@tmp, "GPRINT:i_imap:LAST: Current\\: %5.0lf"); +# push(@tmp, "GPRINT:i_imap:AVERAGE: Average\\: %5.0lf"); +# push(@tmp, "GPRINT:i_imap:MIN: Min\\: %5.0lf"); +# push(@tmp, "GPRINT:i_imap:MAX: Max\\: %5.0lf\\n"); + push(@tmp, "AREA:i_smb#EEEE44:Samba"); + push(@tmp, "GPRINT:i_smb:LAST: Current\\: %5.0lf"); + push(@tmp, "GPRINT:i_smb:AVERAGE: Average\\: %5.0lf"); + push(@tmp, "GPRINT:i_smb:MIN: Min\\: %5.0lf"); + push(@tmp, "GPRINT:i_smb:MAX: Max\\: %5.0lf\\n"); + push(@tmp, "AREA:i_fax#FFA500:Fax"); + push(@tmp, "GPRINT:i_fax:LAST: Current\\: %5.0lf"); + push(@tmp, "GPRINT:i_fax:AVERAGE: Average\\: %5.0lf"); + push(@tmp, "GPRINT:i_fax:MIN: Min\\: %5.0lf"); + push(@tmp, "GPRINT:i_fax:MAX: Max\\: %5.0lf\\n"); + push(@tmp, "AREA:i_cups#444444:CUPS"); + push(@tmp, "GPRINT:i_cups:LAST: Current\\: %5.0lf"); + push(@tmp, "GPRINT:i_cups:AVERAGE: Average\\: %5.0lf"); + push(@tmp, "GPRINT:i_cups:MIN: Min\\: %5.0lf"); + push(@tmp, "GPRINT:i_cups:MAX: Max\\: %5.0lf\\n"); + push(@tmp, "AREA:i_f2b#EE4444:Fail2ban"); + push(@tmp, "GPRINT:i_f2b:LAST: Current\\: %5.0lf"); + push(@tmp, "GPRINT:i_f2b:AVERAGE: Average\\: %5.0lf"); + push(@tmp, "GPRINT:i_f2b:MIN: Min\\: %5.0lf"); + push(@tmp, "GPRINT:i_f2b:MAX: Max\\: %5.0lf\\n"); + push(@tmp, "LINE2:i_ssh#4444EE"); + push(@tmp, "LINE2:i_ftp#44EE44"); + push(@tmp, "LINE2:i_telnet#EE44EE"); +# push(@tmp, "LINE2:i_imap#44EEEE"); + push(@tmp, "LINE2:i_smb#EEEE44"); + push(@tmp, "LINE2:i_fax#FFA500"); + push(@tmp, "LINE2:i_cups#444444"); + push(@tmp, "LINE2:i_f2b#EE4444"); + push(@tmp, "COMMENT: \\n"); + + push(@tmpz, "AREA:i_ssh#4444EE:SSH"); + push(@tmpz, "AREA:i_ftp#44EE44:FTP"); + push(@tmpz, "AREA:i_telnet#EE44EE:Telnet"); +# push(@tmpz, "AREA:i_imap#44EEEE:IMAP"); + push(@tmpz, "AREA:i_smb#EEEE44:Samba"); + push(@tmpz, "AREA:i_fax#FFA500:Fax"); + push(@tmpz, "AREA:i_cups#444444:CUPS"); + push(@tmpz, "AREA:i_f2b#EE4444:Fail2ban"); + push(@tmpz, "LINE2:i_ssh#4444EE"); + push(@tmpz, "LINE2:i_ftp#44EE44"); + push(@tmpz, "LINE2:i_telnet#EE44EE"); +# push(@tmpz, "LINE2:i_imap#44EEEE"); + push(@tmpz, "LINE2:i_smb#EEEE44"); + push(@tmpz, "LINE2:i_fax#FFA500"); + push(@tmpz, "LINE2:i_cups#444444"); + push(@tmpz, "LINE2:i_f2b#EE4444"); + } + + if($title) { + print(" \n"); + print(" \n"); + } + ($width, $height) = split('x', $GRAPH_SIZE{main}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG1", + "--title=$rgraphs{_serv1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=$vlabel", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:i_ssh=$SERV_RRD:serv_i_ssh:AVERAGE", + "DEF:i_ftp=$SERV_RRD:serv_i_ftp:AVERAGE", + "DEF:i_telnet=$SERV_RRD:serv_i_telnet:AVERAGE", + "DEF:i_imap=$SERV_RRD:serv_i_imap:AVERAGE", + "DEF:i_smb=$SERV_RRD:serv_i_smb:AVERAGE", + "DEF:i_fax=$SERV_RRD:serv_i_fax:AVERAGE", + "DEF:i_cups=$SERV_RRD:serv_i_cups:AVERAGE", + "DEF:i_f2b=$SERV_RRD:serv_i_f2b:AVERAGE", + "DEF:l_ssh=$SERV_RRD:serv_l_ssh:AVERAGE", + "DEF:l_ftp=$SERV_RRD:serv_l_ftp:AVERAGE", + "DEF:l_telnet=$SERV_RRD:serv_l_telnet:AVERAGE", + "DEF:l_imap=$SERV_RRD:serv_l_imap:AVERAGE", + "DEF:l_smb=$SERV_RRD:serv_l_smb:AVERAGE", + "DEF:l_fax=$SERV_RRD:serv_l_fax:AVERAGE", + "DEF:l_cups=$SERV_RRD:serv_l_cups:AVERAGE", + "DEF:l_f2b=$SERV_RRD:serv_l_f2b:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG1: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG1z", + "--title=$rgraphs{_serv1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=$vlabel", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:i_ssh=$SERV_RRD:serv_i_ssh:AVERAGE", + "DEF:i_ftp=$SERV_RRD:serv_i_ftp:AVERAGE", + "DEF:i_telnet=$SERV_RRD:serv_i_telnet:AVERAGE", + "DEF:i_imap=$SERV_RRD:serv_i_imap:AVERAGE", + "DEF:i_smb=$SERV_RRD:serv_i_smb:AVERAGE", + "DEF:i_fax=$SERV_RRD:serv_i_fax:AVERAGE", + "DEF:i_cups=$SERV_RRD:serv_i_cups:AVERAGE", + "DEF:i_f2b=$SERV_RRD:serv_i_f2b:AVERAGE", + "DEF:l_ssh=$SERV_RRD:serv_l_ssh:AVERAGE", + "DEF:l_ftp=$SERV_RRD:serv_l_ftp:AVERAGE", + "DEF:l_telnet=$SERV_RRD:serv_l_telnet:AVERAGE", + "DEF:l_imap=$SERV_RRD:serv_l_imap:AVERAGE", + "DEF:l_smb=$SERV_RRD:serv_l_smb:AVERAGE", + "DEF:l_fax=$SERV_RRD:serv_l_fax:AVERAGE", + "DEF:l_cups=$SERV_RRD:serv_l_cups:AVERAGE", + "DEF:l_f2b=$SERV_RRD:serv_l_f2b:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG1z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /serv1/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + if($title) { + print(" \n"); + print(" \n"); + } + + undef(@tmp); + undef(@tmpz); + if($SERV_MODE eq "L") { + $vlabel = "Accesses/s"; + push(@tmp, "AREA:l_imap#4444EE:IMAP"); + push(@tmp, "GPRINT:l_imap:LAST: Current\\: %4.2lf\\n"); + push(@tmp, "AREA:l_pop3#44EE44:POP3"); + push(@tmp, "GPRINT:l_pop3:LAST: Current\\: %4.2lf\\n"); + push(@tmp, "LINE1:l_imap#4444EE:"); + push(@tmp, "LINE1:l_pop3#44EE44:"); + push(@tmpz, "AREA:l_imap#4444EE:IMAP"); + push(@tmpz, "AREA:l_pop3#44EE44:POP3"); + push(@tmpz, "LINE2:l_imap#4444EE:"); + push(@tmpz, "LINE2:l_pop3#44EE44:"); + } else { + $vlabel = "Incremental hits"; + push(@tmp, "AREA:i_imap#4444EE:IMAP"); + push(@tmp, "GPRINT:i_imap:LAST: Current\\: %5.0lf\\n"); + push(@tmp, "AREA:i_pop3#44EE44:POP3"); + push(@tmp, "GPRINT:i_pop3:LAST: Current\\: %5.0lf\\n"); + push(@tmp, "LINE1:i_imap#4444EE:"); + push(@tmp, "LINE1:i_pop3#44EE44:"); + push(@tmpz, "AREA:i_imap#4444EE:IMAP"); + push(@tmpz, "AREA:i_pop3#44EE44:POP3"); + push(@tmpz, "LINE2:i_imap#4444EE:"); + push(@tmpz, "LINE2:i_pop3#44EE44:"); + } + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG2", + "--title=$rgraphs{_serv2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=$vlabel", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:i_imap=$SERV_RRD:serv_i_imap:AVERAGE", + "DEF:l_imap=$SERV_RRD:serv_l_imap:AVERAGE", + "DEF:i_pop3=$SERV_RRD:serv_i_pop3:AVERAGE", + "DEF:l_pop3=$SERV_RRD:serv_l_pop3:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG2: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG2z", + "--title=$rgraphs{_serv2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=$vlabel", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:i_imap=$SERV_RRD:serv_i_imap:AVERAGE", + "DEF:l_imap=$SERV_RRD:serv_l_imap:AVERAGE", + "DEF:i_pop3=$SERV_RRD:serv_i_pop3:AVERAGE", + "DEF:l_pop3=$SERV_RRD:serv_l_pop3:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG2z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /serv2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@tmp); + undef(@tmpz); + if($SERV_MODE eq "L") { + $vlabel = "Accesses/s"; + push(@tmp, "AREA:l_smtp#44EEEE:SMTP"); + push(@tmp, "GPRINT:l_smtp:LAST: Current\\: %4.2lf\\n"); + push(@tmp, "AREA:l_spam#EEEE44:Spam"); + push(@tmp, "GPRINT:l_spam:LAST: Current\\: %4.2lf\\n"); + push(@tmp, "AREA:l_virus#EE4444:Virus"); + push(@tmp, "GPRINT:l_virus:LAST: Current\\: %4.2lf\\n"); + push(@tmp, "LINE2:l_smtp#44EEEE"); + push(@tmp, "LINE2:l_spam#EEEE44"); + push(@tmp, "LINE2:l_virus#EE4444"); + + push(@tmpz, "AREA:l_smtp#44EEEE:SMTP"); + push(@tmpz, "AREA:l_spam#EEEE44:Spam"); + push(@tmpz, "AREA:l_virus#EE4444:Virus"); + push(@tmpz, "LINE2:l_smtp#44EEEE"); + push(@tmpz, "LINE2:l_spam#EEEE44"); + push(@tmpz, "LINE2:l_virus#EE4444"); + } else { + $vlabel = "Incremental hits"; + push(@tmp, "AREA:i_smtp#44EEEE:SMTP"); + push(@tmp, "GPRINT:i_smtp:LAST: Current\\: %5.0lf\\n"); + push(@tmp, "AREA:i_spam#EEEE44:Spam"); + push(@tmp, "GPRINT:i_spam:LAST: Current\\: %5.0lf\\n"); + push(@tmp, "AREA:i_virus#EE4444:Virus"); + push(@tmp, "GPRINT:i_virus:LAST: Current\\: %5.0lf\\n"); + push(@tmp, "LINE2:i_smtp#44EEEE"); + push(@tmp, "LINE2:i_spam#EEEE44"); + push(@tmp, "LINE2:i_virus#EE4444"); + + push(@tmpz, "AREA:i_smtp#44EEEE:SMTP"); + push(@tmpz, "AREA:i_spam#EEEE44:Spam"); + push(@tmpz, "AREA:i_virus#EE4444:Virus"); + push(@tmpz, "LINE2:i_smtp#44EEEE"); + push(@tmpz, "LINE2:i_spam#EEEE44"); + push(@tmpz, "LINE2:i_virus#EE4444"); + } + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG3", + "--title=$rgraphs{_serv3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=$vlabel", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:i_smtp=$SERV_RRD:serv_i_smtp:AVERAGE", + "DEF:i_spam=$SERV_RRD:serv_i_spam:AVERAGE", + "DEF:i_virus=$SERV_RRD:serv_i_virus:AVERAGE", + "DEF:l_smtp=$SERV_RRD:serv_l_smtp:AVERAGE", + "DEF:l_spam=$SERV_RRD:serv_l_spam:AVERAGE", + "DEF:l_virus=$SERV_RRD:serv_l_virus:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG3: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + undef(@tmp); + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG3z", + "--title=$rgraphs{_serv3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=$vlabel", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:i_smtp=$SERV_RRD:serv_i_smtp:AVERAGE", + "DEF:i_spam=$SERV_RRD:serv_i_spam:AVERAGE", + "DEF:i_virus=$SERV_RRD:serv_i_virus:AVERAGE", + "DEF:l_smtp=$SERV_RRD:serv_l_smtp:AVERAGE", + "DEF:l_spam=$SERV_RRD:serv_l_spam:AVERAGE", + "DEF:l_virus=$SERV_RRD:serv_l_virus:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG3z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /serv3/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; +} + +# MAIL graph +# ---------------------------------------------------------------------------- +sub mail { + my ($myself, $title) = @_; + + my $width; + my $height; + my @riglim; + my $T = "B"; + my $vlabel = "bytes/s"; + my @tmp; + my @tmpz; + my @CDEF; + my $n; + my $str; + my $err; + + my $PNG1 = $u . $myself . "1." . $when . ".png"; + my $PNG2 = $u . $myself . "2." . $when . ".png"; + my $PNG3 = $u . $myself . "3." . $when . ".png"; + my $PNG4 = $u . $myself . "4." . $when . ".png"; + my $PNG5 = $u . $myself . "5." . $when . ".png"; + my $PNG1z = $u . $myself . "1z." . $when . ".png"; + my $PNG2z = $u . $myself . "2z." . $when . ".png"; + my $PNG3z = $u . $myself . "3z." . $when . ".png"; + my $PNG4z = $u . $myself . "4z." . $when . ".png"; + my $PNG5z = $u . $myself . "5z." . $when . ".png"; + + $title = !$silent ? $title : ""; + + unlink ("$PNG_DIR" . "$PNG1", + "$PNG_DIR" . "$PNG2", + "$PNG_DIR" . "$PNG3", + "$PNG_DIR" . "$PNG4", + "$PNG_DIR" . "$PNG5"); + if($ENABLE_ZOOM eq "Y") { + unlink ("$PNG_DIR" . "$PNG1z", + "$PNG_DIR" . "$PNG2z", + "$PNG_DIR" . "$PNG3z", + "$PNG_DIR" . "$PNG4z", + "$PNG_DIR" . "$PNG5z"); + } + + if($NETSTATS_IN_BPS eq "Y") { + $T = "b"; + $vlabel = "bits/s"; + } + + if($IFACE_MODE eq "text") { + if($title) { + graph_header($title, 2); + print(" \n"); + print(" \n"); + } + my (undef, undef, undef, $data) = RRDs::fetch("$MAIL_RRD", + "--start=-$nwhen$twhen", + "AVERAGE", + "-r $res"); + $err = RRDs::error; + print("ERROR: while fetching $MAIL_RRD: $err\n") if $err; + print("
\n");
+		print("Time  In.Conn Out.Conn  Receivd   Delivd  Bytes.R  Bytes.D  Rejectd  Bounced  Discard     Held  Forward     Spam    Virus   Queued  Queue.S\n");
+		print("------------------------------------------------------------------------------------------------------------------------------------------- \n");
+		my $line;
+		my @row;
+		my $time;
+		for($n = 0, $time = $tb; $n < ($tb * $ts); $n++) {
+			$line = @$data[$n];
+			$time = $time - (1 / $ts);
+			my ($in, $out, $recvd, $delvd, $bytes_recvd, $bytes_delvd, $rejtd, $spam, $virus, $bouncd, $queued, $discrd, $held, $forwrd, $queues) = @$line;
+			@row = ($in, $out, $recvd, $delvd, $bytes_recvd, $bytes_delvd, $rejtd, $bouncd, $discrd, $held, $forwrd, $spam, $virus, $queued, $queues);
+			printf(" %2d$tc  %7.2f  %7.2f  %7.2f  %7.2f  %7.2f  %7.2f  %7.2f  %7.2f  %7.2f  %7.2f  %7.2f  %7.2f  %7.2f  %7.2f  %7.2f\n", $time, @row);
+		}
+		print("    
\n"); + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; + } + + if($title) { + graph_header($title, 2); + } + if(lc($MAIL_MTA) eq "sendmail") { + push(@tmp, "AREA:in#44EE44:In Connections"); + push(@tmp, "GPRINT:in:LAST: Cur\\: %5.2lf"); + push(@tmp, "GPRINT:in:AVERAGE: Avg\\: %5.2lf"); + push(@tmp, "GPRINT:in:MIN: Min\\: %5.2lf"); + push(@tmp, "GPRINT:in:MAX: Max\\: %5.2lf\\n"); + push(@tmp, "AREA:rejtd#EE4444:Rejected"); + push(@tmp, "GPRINT:rejtd:LAST: Cur\\: %5.2lf"); + push(@tmp, "GPRINT:rejtd:AVERAGE: Avg\\: %5.2lf"); + push(@tmp, "GPRINT:rejtd:MIN: Min\\: %5.2lf"); + push(@tmp, "GPRINT:rejtd:MAX: Max\\: %5.2lf\\n"); + push(@tmp, "AREA:recvd#448844:Received"); + push(@tmp, "GPRINT:recvd:LAST: Cur\\: %5.2lf"); + push(@tmp, "GPRINT:recvd:AVERAGE: Avg\\: %5.2lf"); + push(@tmp, "GPRINT:recvd:MIN: Min\\: %5.2lf"); + push(@tmp, "GPRINT:recvd:MAX: Max\\: %5.2lf\\n"); + push(@tmp, "AREA:spam#EEEE44:Spam"); + push(@tmp, "GPRINT:spam:LAST: Cur\\: %5.2lf"); + push(@tmp, "GPRINT:spam:AVERAGE: Avg\\: %5.2lf"); + push(@tmp, "GPRINT:spam:MIN: Min\\: %5.2lf"); + push(@tmp, "GPRINT:spam:MAX: Max\\: %5.2lf\\n"); + push(@tmp, "AREA:virus#EE44EE:Virus"); + push(@tmp, "GPRINT:virus:LAST: Cur\\: %5.2lf"); + push(@tmp, "GPRINT:virus:AVERAGE: Avg\\: %5.2lf"); + push(@tmp, "GPRINT:virus:MIN: Min\\: %5.2lf"); + push(@tmp, "GPRINT:virus:MAX: Max\\: %5.2lf\\n"); + push(@tmp, "AREA:n_delvd#4444EE:Delivered"); + push(@tmp, "GPRINT:delvd:LAST: Cur\\: %5.2lf"); + push(@tmp, "GPRINT:delvd:AVERAGE: Avg\\: %5.2lf"); + push(@tmp, "GPRINT:delvd:MIN: Min\\: %5.2lf"); + push(@tmp, "GPRINT:delvd:MAX: Max\\: %5.2lf\\n"); + push(@tmp, "AREA:n_out#44EEEE:Out Connections"); + push(@tmp, "GPRINT:out:LAST: Cur\\: %5.2lf"); + push(@tmp, "GPRINT:out:AVERAGE: Avg\\: %5.2lf"); + push(@tmp, "GPRINT:out:MIN: Min\\: %5.2lf"); + push(@tmp, "GPRINT:out:MAX: Max\\: %5.2lf\\n"); + push(@tmp, "LINE1:in#00EE00"); + push(@tmp, "LINE1:rejtd#EE0000"); + push(@tmp, "LINE1:recvd#1F881F"); + push(@tmp, "LINE1:spam#EEEE00"); + push(@tmp, "LINE1:virus#EE00EE"); + push(@tmp, "LINE1:n_delvd#0000EE"); + push(@tmp, "LINE1:n_out#00EEEE"); + + push(@tmpz, "AREA:in#44EE44:In Connections"); + push(@tmpz, "AREA:rejtd#EE4444:Rejected"); + push(@tmpz, "AREA:recvd#448844:Received"); + push(@tmpz, "AREA:spam#EEEE44:Spam"); + push(@tmpz, "AREA:virus#EE44EE:Virus"); + push(@tmpz, "AREA:n_delvd#4444EE:Delivered"); + push(@tmpz, "AREA:n_out#44EEEE:Out Connections"); + push(@tmpz, "LINE1:in#00EE00"); + push(@tmpz, "LINE1:rejtd#EE0000"); + push(@tmpz, "LINE1:recvd#1F881F"); + push(@tmpz, "LINE1:spam#EEEE00"); + push(@tmpz, "LINE1:virus#EE00EE"); + push(@tmpz, "LINE1:n_delvd#0000EE"); + push(@tmpz, "LINE1:n_out#00EEEE"); + } elsif(lc($MAIL_MTA eq "postfix")) { + push(@tmp, "AREA:rejtd#EE4444:Rejected"); + push(@tmp, "GPRINT:rejtd:LAST: Cur\\: %5.2lf"); + push(@tmp, "GPRINT:rejtd:AVERAGE: Avg\\: %5.2lf"); + push(@tmp, "GPRINT:rejtd:MIN: Min\\: %5.2lf"); + push(@tmp, "GPRINT:rejtd:MAX: Max\\: %5.2lf\\n"); + push(@tmp, "AREA:recvd#448844:Received"); + push(@tmp, "GPRINT:recvd:LAST: Cur\\: %5.2lf"); + push(@tmp, "GPRINT:recvd:AVERAGE: Avg\\: %5.2lf"); + push(@tmp, "GPRINT:recvd:MIN: Min\\: %5.2lf"); + push(@tmp, "GPRINT:recvd:MAX: Max\\: %5.2lf\\n"); + push(@tmp, "AREA:spam#EEEE44:Spam"); + push(@tmp, "GPRINT:spam:LAST: Cur\\: %5.2lf"); + push(@tmp, "GPRINT:spam:AVERAGE: Avg\\: %5.2lf"); + push(@tmp, "GPRINT:spam:MIN: Min\\: %5.2lf"); + push(@tmp, "GPRINT:spam:MAX: Max\\: %5.2lf\\n"); + push(@tmp, "AREA:virus#EE44EE:Virus"); + push(@tmp, "GPRINT:virus:LAST: Cur\\: %5.2lf"); + push(@tmp, "GPRINT:virus:AVERAGE: Avg\\: %5.2lf"); + push(@tmp, "GPRINT:virus:MIN: Min\\: %5.2lf"); + push(@tmp, "GPRINT:virus:MAX: Max\\: %5.2lf\\n"); + push(@tmp, "AREA:bouncd#FFA500:Bounced"); + push(@tmp, "GPRINT:bouncd:LAST: Cur\\: %5.2lf"); + push(@tmp, "GPRINT:bouncd:AVERAGE: Avg\\: %5.2lf"); + push(@tmp, "GPRINT:bouncd:MIN: Min\\: %5.2lf"); + push(@tmp, "GPRINT:bouncd:MAX: Max\\: %5.2lf\\n"); + push(@tmp, "AREA:discrd#CCCCCC:Discarded"); + push(@tmp, "GPRINT:discrd:LAST: Cur\\: %5.2lf"); + push(@tmp, "GPRINT:discrd:AVERAGE: Avg\\: %5.2lf"); + push(@tmp, "GPRINT:discrd:MIN: Min\\: %5.2lf"); + push(@tmp, "GPRINT:discrd:MAX: Max\\: %5.2lf\\n"); + push(@tmp, "AREA:held#44EE44:Held"); + push(@tmp, "GPRINT:held:LAST: Cur\\: %5.2lf"); + push(@tmp, "GPRINT:held:AVERAGE: Avg\\: %5.2lf"); + push(@tmp, "GPRINT:held:MIN: Min\\: %5.2lf"); + push(@tmp, "GPRINT:held:MAX: Max\\: %5.2lf\\n"); + push(@tmp, "AREA:n_forwrd#44EEEE:Forwarded"); + push(@tmp, "GPRINT:forwrd:LAST: Cur\\: %5.2lf"); + push(@tmp, "GPRINT:forwrd:AVERAGE: Avg\\: %5.2lf"); + push(@tmp, "GPRINT:forwrd:MIN: Min\\: %5.2lf"); + push(@tmp, "GPRINT:forwrd:MAX: Max\\: %5.2lf\\n"); + push(@tmp, "AREA:n_delvd#4444EE:Delivered"); + push(@tmp, "GPRINT:delvd:LAST: Cur\\: %5.2lf"); + push(@tmp, "GPRINT:delvd:AVERAGE: Avg\\: %5.2lf"); + push(@tmp, "GPRINT:delvd:MIN: Min\\: %5.2lf"); + push(@tmp, "GPRINT:delvd:MAX: Max\\: %5.2lf\\n"); + push(@tmp, "LINE1:rejtd#EE0000"); + push(@tmp, "LINE1:recvd#1F881F"); + push(@tmp, "LINE1:spam#EEEE00"); + push(@tmp, "LINE1:virus#EE00EE"); + push(@tmp, "LINE1:bouncd#FFA500"); + push(@tmp, "LINE1:discrd#888888"); + push(@tmp, "LINE1:held#00EE00"); + push(@tmp, "LINE1:n_forwrd#00EEEE"); + push(@tmp, "LINE1:n_delvd#0000EE"); + + push(@tmpz, "AREA:rejtd#EE4444:Rejected"); + push(@tmpz, "AREA:recvd#448844:Received"); + push(@tmpz, "AREA:spam#EEEE44:Spam"); + push(@tmpz, "AREA:virus#EE44EE:Virus"); + push(@tmpz, "AREA:bouncd#FFA500:Bounced"); + push(@tmpz, "AREA:discrd#888888:Discarded"); + push(@tmpz, "AREA:held#44EE44:Held"); + push(@tmpz, "AREA:n_forwrd#44EEEE:Forwarded"); + push(@tmpz, "AREA:n_delvd#4444EE:Delivered"); + push(@tmpz, "LINE1:rejtd#EE0000"); + push(@tmpz, "LINE1:recvd#1F881F"); + push(@tmpz, "LINE1:spam#EEEE00"); + push(@tmpz, "LINE1:virus#EE00EE"); + push(@tmpz, "LINE1:bouncd#FFA500"); + push(@tmpz, "LINE1:discrd#888888"); + push(@tmpz, "LINE1:held#00EE00"); + push(@tmpz, "LINE1:n_forwrd#00EEEE"); + push(@tmpz, "LINE1:n_delvd#0000EE"); + } + + if($title) { + print(" \n"); + print(" \n"); + } + + undef(@riglim); + if($MAIL1_RIGID eq 1) { + push(@riglim, "--upper-limit=$MAIL1_LIMIT"); + } else { + if($MAIL1_RIGID eq 2) { + push(@riglim, "--upper-limit=$MAIL1_LIMIT"); + push(@riglim, "--rigid"); + } + } + ($width, $height) = split('x', $GRAPH_SIZE{main}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG1", + "--title=$rgraphs{_mail1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Messages/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:in=$MAIL_RRD:mail_in:AVERAGE", + "DEF:out=$MAIL_RRD:mail_out:AVERAGE", + "DEF:recvd=$MAIL_RRD:mail_recvd:AVERAGE", + "DEF:delvd=$MAIL_RRD:mail_delvd:AVERAGE", + "DEF:bytes_recvd=$MAIL_RRD:mail_bytes_recvd:AVERAGE", + "DEF:bytes_delvd=$MAIL_RRD:mail_bytes_delvd:AVERAGE", + "DEF:rejtd=$MAIL_RRD:mail_rejtd:AVERAGE", + "DEF:spam=$MAIL_RRD:mail_spam:AVERAGE", + "DEF:virus=$MAIL_RRD:mail_virus:AVERAGE", + "DEF:bouncd=$MAIL_RRD:mail_bouncd:AVERAGE", + "DEF:discrd=$MAIL_RRD:mail_discrd:AVERAGE", + "DEF:held=$MAIL_RRD:mail_held:AVERAGE", + "DEF:forwrd=$MAIL_RRD:mail_forwrd:AVERAGE", + "CDEF:n_forwrd=forwrd,-1,*", + "CDEF:n_delvd=delvd,-1,*", + "CDEF:n_out=out,-1,*", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG1: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG1z", + "--title=$rgraphs{_mail1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Messages/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:in=$MAIL_RRD:mail_in:AVERAGE", + "DEF:out=$MAIL_RRD:mail_out:AVERAGE", + "DEF:recvd=$MAIL_RRD:mail_recvd:AVERAGE", + "DEF:delvd=$MAIL_RRD:mail_delvd:AVERAGE", + "DEF:bytes_recvd=$MAIL_RRD:mail_bytes_recvd:AVERAGE", + "DEF:bytes_delvd=$MAIL_RRD:mail_bytes_delvd:AVERAGE", + "DEF:rejtd=$MAIL_RRD:mail_rejtd:AVERAGE", + "DEF:spam=$MAIL_RRD:mail_spam:AVERAGE", + "DEF:virus=$MAIL_RRD:mail_virus:AVERAGE", + "DEF:bouncd=$MAIL_RRD:mail_bouncd:AVERAGE", + "DEF:discrd=$MAIL_RRD:mail_discrd:AVERAGE", + "DEF:held=$MAIL_RRD:mail_held:AVERAGE", + "DEF:forwrd=$MAIL_RRD:mail_forwrd:AVERAGE", + "CDEF:n_forwrd=forwrd,-1,*", + "CDEF:n_delvd=delvd,-1,*", + "CDEF:n_out=out,-1,*", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG1z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /mail1/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@riglim); + if($MAIL2_RIGID eq 1) { + push(@riglim, "--upper-limit=$MAIL2_LIMIT"); + } else { + if($MAIL2_RIGID eq 2) { + push(@riglim, "--upper-limit=$MAIL2_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + push(@tmp, "AREA:B_in#44EE44:K$T/s Received"); + push(@tmp, "GPRINT:K_in:LAST: Cur\\: %5.0lf"); + push(@tmp, "GPRINT:K_in:AVERAGE: Avg\\: %5.0lf"); + push(@tmp, "GPRINT:K_in:MIN: Min\\: %5.0lf"); + push(@tmp, "GPRINT:K_in:MAX: Max\\: %5.0lf\\n"); + push(@tmp, "AREA:B_out#4444EE:K$T/s Delivered"); + push(@tmp, "GPRINT:K_out:LAST: Cur\\: %5.0lf"); + push(@tmp, "GPRINT:K_out:AVERAGE: Avg\\: %5.0lf"); + push(@tmp, "GPRINT:K_out:MIN: Min\\: %5.0lf"); + push(@tmp, "GPRINT:K_out:MAX: Max\\: %5.0lf\\n"); + push(@tmp, "AREA:B_out#4444EE:"); + push(@tmp, "AREA:B_in#44EE44:"); + push(@tmp, "LINE1:B_out#0000EE"); + push(@tmp, "LINE1:B_in#00EE00"); + push(@tmpz, "AREA:B_in#44EE44:Received"); + push(@tmpz, "AREA:B_out#4444EE:Delivered"); + push(@tmpz, "AREA:B_out#4444EE:"); + push(@tmpz, "AREA:B_in#44EE44:"); + push(@tmpz, "LINE1:B_out#0000EE"); + push(@tmpz, "LINE1:B_in#00EE00"); + if($NETSTATS_IN_BPS eq "Y") { + push(@CDEF, "CDEF:B_in=in,8,*"); + push(@CDEF, "CDEF:B_out=out,8,*"); + } else { + push(@CDEF, "CDEF:B_in=in"); + push(@CDEF, "CDEF:B_out=out"); + } + ($width, $height) = split('x', $GRAPH_SIZE{main}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + } + + RRDs::graph("$PNG_DIR" . "$PNG2", + "--title=$rgraphs{_mail2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=$vlabel", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:in=$MAIL_RRD:mail_bytes_recvd:AVERAGE", + "DEF:out=$MAIL_RRD:mail_bytes_delvd:AVERAGE", + @CDEF, + "CDEF:K_in=B_in,1024,/", + "CDEF:K_out=B_out,1024,/", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG2: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG2z", + "--title=$rgraphs{_mail2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=$vlabel", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:in=$MAIL_RRD:mail_bytes_recvd:AVERAGE", + "DEF:out=$MAIL_RRD:mail_bytes_delvd:AVERAGE", + @CDEF, + "CDEF:K_in=B_in,1024,/", + "CDEF:K_out=B_out,1024,/", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG2z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /mail2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + if($title) { + print(" \n"); + print(" \n"); + } + + undef(@riglim); + if($MAIL3_RIGID eq 1) { + push(@riglim, "--upper-limit=$MAIL3_LIMIT"); + } else { + if($MAIL3_RIGID eq 2) { + push(@riglim, "--upper-limit=$MAIL3_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + push(@tmp, "AREA:queued#EEEE44:Queued"); + push(@tmp, "LINE1:queued#EEEE00"); + push(@tmp, "GPRINT:queued:LAST: Current\\: %5.0lf\\n"); + push(@tmpz, "AREA:queued#EEEE44:Queued"); + push(@tmpz, "LINE1:queued#EEEE00"); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG3", + "--title=$rgraphs{_mail3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Messages", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:queued=$MAIL_RRD:mail_queued:AVERAGE", + "COMMENT: \\n", + @tmp, + "COMMENT: \\n", + "COMMENT: \\n"); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG3: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG3z", + "--title=$rgraphs{_mail3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Messages", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:queued=$MAIL_RRD:mail_queued:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG3z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /mail3/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@riglim); + if($MAIL4_RIGID eq 1) { + push(@riglim, "--upper-limit=$MAIL4_LIMIT"); + } else { + if($MAIL4_RIGID eq 2) { + push(@riglim, "--upper-limit=$MAIL4_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + push(@tmp, "AREA:queues#44AAEE:Size in KB"); + push(@tmp, "LINE1:queues#00AAEE"); + push(@tmp, "GPRINT:K_queues:LAST: Current\\: %5.1lf\\n"); + push(@tmpz, "AREA:queues#44AAEE:Size"); + push(@tmpz, "LINE1:queues#00AAEE"); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG4", + "--title=$rgraphs{_mail4} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Bytes", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:queues=$MAIL_RRD:mail_queues:AVERAGE", + "CDEF:K_queues=queues,1024,/", + "COMMENT: \\n", + @tmp, + "COMMENT: \\n", + "COMMENT: \\n"); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG4: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG4z", + "--title=$rgraphs{_mail4} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Bytes", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:queues=$MAIL_RRD:mail_queues:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG4z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /mail4/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@riglim); + if($MAIL5_RIGID eq 1) { + push(@riglim, "--upper-limit=$MAIL5_LIMIT"); + } else { + if($MAIL5_RIGID eq 2) { + push(@riglim, "--upper-limit=$MAIL5_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + push(@tmp, "AREA:greylisted#4444EE:Greylisted"); + push(@tmp, "GPRINT:greylisted:LAST: Current\\: %5.0lf\\n"); + push(@tmp, "AREA:whitelisted#44EEEE:Whitelisted"); + push(@tmp, "GPRINT:whitelisted:LAST: Current\\: %5.0lf\\n"); + push(@tmp, "LINE1:greylisted#0000EE"); + push(@tmp, "LINE1:whitelisted#00EEEE"); + push(@tmp, "LINE1:records#EE0000:Records"); + push(@tmp, "GPRINT:records:LAST: Current\\: %5.0lf\\n"); + push(@tmpz, "AREA:greylisted#4444EE:Greylisted"); + push(@tmpz, "AREA:whitelisted#44EEEE:Whitelisted"); + push(@tmpz, "LINE2:greylisted#0000EE"); + push(@tmpz, "LINE2:whitelisted#00EEEE"); + push(@tmpz, "LINE2:records#EE0000:Records"); + if(lc($MAIL_MTA eq "postfix")) { + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG5", + "--title=$rgraphs{_mail5} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Messages", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:records=$MAIL_RRD:mail_val07:AVERAGE", + "DEF:greylisted=$MAIL_RRD:mail_val08:AVERAGE", + "DEF:whitelisted=$MAIL_RRD:mail_val09:AVERAGE", + "COMMENT: \\n", + "COMMENT: \\n", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG5: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG5z", + "--title=$rgraphs{_mail5} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Messages", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:records=$MAIL_RRD:mail_val07:AVERAGE", + "DEF:greylisted=$MAIL_RRD:mail_val08:AVERAGE", + "DEF:whitelisted=$MAIL_RRD:mail_val09:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG5z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /mail5/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; +} + +# PORT graph +# ---------------------------------------------------------------------------- +sub port { + my ($myself, $title) = @_; + + my $width; + my $height; + my @riglim; + my @warning; + my @PNG; + my @PNGz; + my $addr; + my $stat; + my $name; + my @tmp; + my @tmpz; + my @CDEF; + my $T = "B"; + my $vlabel = "bytes/s"; + my $n; + my $str; + my $err; + + my $PORT_PER_ROW = 3; + $title = !$silent ? $title : ""; + + if($NETSTATS_IN_BPS eq "Y") { + $T = "b"; + $vlabel = "bits/s"; + } + if($IFACE_MODE eq "text") { + my $line2; + my $line3; + if($title) { + graph_header($title, 2); + print(" \n"); + print(" \n"); + } + my (undef, undef, undef, $data) = RRDs::fetch("$PORT_RRD", + "--start=-$nwhen$twhen", + "AVERAGE", + "-r $res"); + $err = RRDs::error; + print("ERROR: while fetching $PORT_RRD: $err\n") if $err; + print("
\n");
+		print("    ");
+		for($n = 0; $n < $PORT_MAX && $n < scalar(@PORT_LIST); $n++) {
+			printf("   %-5s %-8s", $PORT_LIST[$n], substr($PORT_NAME[$n], 0, 8));
+			$line2 .= "   K$T/s_I  K$T/s_O";
+			$line3 .= "-----------------";
+		}
+		print("\n");
+		print("Time$line2\n");
+		print("----$line3 \n");
+		my $line;
+		my @row;
+		my $time;
+		my $n2;
+		my $from;
+		my $to;
+		for($n = 0, $time = $tb; $n < ($tb * $ts); $n++) {
+			$line = @$data[$n];
+			$time = $time - (1 / $ts);
+			printf(" %2d$tc ", $time);
+			for($n2 = 0; $n2 < $PORT_MAX && $n2 < scalar(@PORT_LIST); $n2++) {
+				$from = $n2 * 2;
+				$to = $from + 1;
+				my ($kin, $kout) = @$line[$from..$to];
+				$kin /= 1024;
+				$kout /= 1024;
+				if($NETSTATS_IN_BPS eq "Y") {
+					$kin *= 8;
+					$kout *= 8;
+				}
+				@row = ($kin, $kout);
+				printf("  %6d  %6d ", @row);
+			}
+			print("\n");
+		}
+		print("    
\n"); + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; + } + + for($n = 0; $n < $PORT_MAX; $n++) { + $str = $u . $myself . $n . "." . $when . ".png"; + push(@PNG, $str); + unlink("$PNG_DIR" . $str); + if($ENABLE_ZOOM eq "Y") { + $str = $u . $myself . $n . "z." . $when . ".png"; + push(@PNGz, $str); + unlink("$PNG_DIR" . $str); + } + } + + $n = 0; + while($n < $PORT_MAX && $n < scalar(@PORT_LIST)) { + if($title) { + if($n == 0) { + graph_header($title, $PORT_PER_ROW); + } + print(" \n"); + } + for($n2 = 0; $n2 < $PORT_PER_ROW; $n2++) { + last unless ($n < $PORT_MAX && $n < scalar(@PORT_LIST)); + if($title) { + print(" \n"); + } + undef(@riglim); + if($PORT_RIGID[$n] eq 1) { + push(@riglim, "--upper-limit=$PORT_LIMIT[$n]"); + } else { + if($PORT_RIGID[$n] eq 2) { + push(@riglim, "--upper-limit=$PORT_LIMIT[$n]"); + push(@riglim, "--rigid"); + } + } + + undef(@warning); + if($os eq "Linux") { + open(IN, "netstat -nl --$PORT_PROT[$n] |"); + while() { + (undef, undef, undef, $addr) = split(' ', $_); + chomp($addr); + $addr =~ s/.*://; + if($addr eq $PORT_LIST[$n]) { + last; + } + } + close(IN); + } + if($os eq "FreeBSD" || $os eq "OpenBSD") { + open(IN, "netstat -anl -p $PORT_PROT[$n] |"); + while() { + (undef, undef, undef, $addr, undef, $stat) = split(' ', $_); + chomp($stat); + if($stat eq "LISTEN") { + chomp($addr); + ($addr) = ($addr =~ m/^.*?(\.\d+$)/); + $addr =~ s/\.//; + if($addr eq $PORT_LIST[$n]) { + last; + } + } + } + close(IN); + } + if($addr ne $PORT_LIST[$n]) { + push(@warning, $warning_color); + } + + $name = substr($PORT_NAME[$n], 0, 15); + undef(@tmp); + undef(@tmpz); + undef(@CDEF); + push(@tmp, "AREA:B_in#44EE44:Input"); + push(@tmp, "AREA:B_out#4444EE:Output"); + push(@tmp, "AREA:B_out#4444EE:"); + push(@tmp, "AREA:B_in#44EE44:"); + push(@tmp, "LINE1:B_out#0000EE"); + push(@tmp, "LINE1:B_in#00EE00"); + push(@tmpz, "AREA:B_in#44EE44:Input"); + push(@tmpz, "AREA:B_out#4444EE:Output"); + push(@tmpz, "AREA:B_out#4444EE:"); + push(@tmpz, "AREA:B_in#44EE44:"); + push(@tmpz, "LINE1:B_out#0000EE"); + push(@tmpz, "LINE1:B_in#00EE00"); + if($NETSTATS_IN_BPS eq "Y") { + push(@CDEF, "CDEF:B_in=in,8,*"); + push(@CDEF, "CDEF:B_out=out,8,*"); + } else { + push(@CDEF, "CDEF:B_in=in"); + push(@CDEF, "CDEF:B_out=out"); + } + ($width, $height) = split('x', $GRAPH_SIZE{mini}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG[$n]", + "--title=$name traffic ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=$vlabel", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + @warning, + "DEF:in=$PORT_RRD:port" . $n . "_in:AVERAGE", + "DEF:out=$PORT_RRD:port" . $n . "_out:AVERAGE", + @CDEF, + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG[$n]: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNGz[$n]", + "--title=$name traffic ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=$vlabel", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + @warning, + "DEF:in=$PORT_RRD:port" . $n . "_in:AVERAGE", + "DEF:out=$PORT_RRD:port" . $n . "_out:AVERAGE", + @CDEF, + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNGz[$n]: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /port$n/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + if($title) { + print(" \n"); + } + $n++; + } + if($title) { + print(" \n"); + } + } + if($title) { + graph_footer(); + } + return 1; +} + +# USER graph +# ---------------------------------------------------------------------------- +sub user { + my ($myself, $title) = @_; + + my $width; + my $height; + my @riglim; + my @tmp; + my @tmpz; + my $n; + my $err; + + my $PNG1 = $u . $myself . "1." . $when . ".png"; + my $PNG2 = $u . $myself . "2." . $when . ".png"; + my $PNG3 = $u . $myself . "3." . $when . ".png"; + my $PNG1z = $u . $myself . "1z." . $when . ".png"; + my $PNG2z = $u . $myself . "2z." . $when . ".png"; + my $PNG3z = $u . $myself . "3z." . $when . ".png"; + + $title = !$silent ? $title : ""; + + unlink ("$PNG_DIR" . "$PNG1", + "$PNG_DIR" . "$PNG2", + "$PNG_DIR" . "$PNG3"); + if($ENABLE_ZOOM eq "Y") { + unlink ("$PNG_DIR" . "$PNG1z", + "$PNG_DIR" . "$PNG2z", + "$PNG_DIR" . "$PNG3z"); + } + + if($IFACE_MODE eq "text") { + if($title) { + graph_header($title, 2); + print(" \n"); + print(" \n"); + } + my (undef, undef, undef, $data) = RRDs::fetch("$USER_RRD", + "--start=-$nwhen$twhen", + "AVERAGE", + "-r $res"); + $err = RRDs::error; + print("ERROR: while fetching $USER_RRD: $err\n") if $err; + print("
\n");
+		print("Time    Logged In     Samba  Netatalk\n");
+		print("------------------------------------- \n");
+		my $line;
+		my @row;
+		my $time;
+		for($n = 0, $time = $tb; $n < ($tb * $ts); $n++) {
+			$line = @$data[$n];
+			my ($sys, $smb, $mac) = @$line;
+			@row = ($sys, $smb, $mac);
+			$time = $time - (1 / $ts);
+			printf(" %2d$tc       %6d    %6d    %6d\n", $time, @row);
+		}
+		print("    
\n"); + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; + } + + if($title) { + graph_header($title, 2); + } + if($USER1_RIGID eq 1) { + push(@riglim, "--upper-limit=$USER1_LIMIT"); + } else { + if($USER1_RIGID eq 2) { + push(@riglim, "--upper-limit=$USER1_LIMIT"); + push(@riglim, "--rigid"); + } + } + if($title) { + print(" \n"); + print(" \n"); + } + push(@tmp, "AREA:sys#44EE44:Logged In"); + push(@tmp, "GPRINT:sys:LAST: Current\\: %3.0lf"); + push(@tmp, "GPRINT:sys:AVERAGE: Average\\: %3.0lf"); + push(@tmp, "GPRINT:sys:MIN: Min\\: %3.0lf"); + push(@tmp, "GPRINT:sys:MAX: Max\\: %3.0lf\\n"); + push(@tmp, "LINE1:sys#00EE00"); + push(@tmpz, "AREA:sys#44EE44:Logged In"); + push(@tmpz, "LINE1:sys#00EE00"); + ($width, $height) = split('x', $GRAPH_SIZE{main}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + } + RRDs::graph("$PNG_DIR" . "$PNG1", + "--title=$rgraphs{_user1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Users", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:sys=$USER_RRD:user_sys:AVERAGE", + "COMMENT: \\n", + @tmp, + "COMMENT: \\n", + "COMMENT: \\n", + "COMMENT: \\n"); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG1: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG1z", + "--title=$rgraphs{_user1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Users", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:sys=$USER_RRD:user_sys:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG1z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /user1/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + if($title) { + print(" \n"); + print(" \n"); + } + + undef(@riglim); + if($USER2_RIGID eq 1) { + push(@riglim, "--upper-limit=$USER2_LIMIT"); + } else { + if($USER2_RIGID eq 2) { + push(@riglim, "--upper-limit=$USER2_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + push(@tmp, "AREA:smb#EEEE44:Samba"); + push(@tmp, "GPRINT:smb:LAST: Current\\: %3.0lf\\n"); + push(@tmp, "LINE1:smb#EEEE00"); + push(@tmpz, "AREA:smb#EEEE44:Samba"); + push(@tmpz, "LINE2:smb#EEEE00"); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG2", + "--title=$rgraphs{_user2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Users", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:smb=$USER_RRD:user_smb:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG2: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG2z", + "--title=$rgraphs{_user2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Users", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:smb=$USER_RRD:user_smb:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG2z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /user2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@riglim); + if($USER3_RIGID eq 1) { + push(@riglim, "--upper-limit=$USER3_LIMIT"); + } else { + if($USER3_RIGID eq 2) { + push(@riglim, "--upper-limit=$USER3_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + push(@tmp, "AREA:mac#EE4444:Netatalk"); + push(@tmp, "GPRINT:mac:LAST: Current\\: %3.0lf\\n"); + push(@tmp, "LINE1:mac#EE0000"); + push(@tmpz, "AREA:mac#EE4444:Netatalk"); + push(@tmpz, "LINE2:mac#EE0000"); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG3", + "--title=$rgraphs{_user3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Users", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:mac=$USER_RRD:user_mac:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG3: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG3z", + "--title=$rgraphs{_user3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Users", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:mac=$USER_RRD:user_mac:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG3z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /user3/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; +} + +# APACHE graph +# ---------------------------------------------------------------------------- +sub apache { + my ($myself, $title) = @_; + + my $width; + my $height; + my @riglim; + my @PNG; + my @PNGz; + my @tmp; + my @tmpz; + my $e; + my $e2; + my $n; + my $n2; + my $str; + my $err; + + $title = !$silent ? $title : ""; + + if($IFACE_MODE eq "text") { + my $line1; + my $line2; + my $line3; + if($title) { + graph_header($title, 2); + print(" \n"); + print(" \n"); + } + my (undef, undef, undef, $data) = RRDs::fetch("$APACHE_RRD", + "--start=-$nwhen$twhen", + "AVERAGE", + "-r $res"); + $err = RRDs::error; + print("ERROR: while fetching $APACHE_RRD: $err\n") if $err; + print("
\n");
+		print("    ");
+		for($n = 0; $n < scalar(@APACHE_LIST); $n++) {
+			$line1 = "                                          ";
+			$line2 .= "   Acceses     kbytes      CPU  Busy  Idle";
+			$line3 .= "------------------------------------------";
+			if($line1) {
+				$i = length($line1);
+				printf(sprintf("%${i}s", sprintf("%s", $APACHE_LIST[$n])));
+			}
+		}
+		print("\n");
+		print("Time$line2\n");
+		print("----$line3 \n");
+		my $line;
+		my @row;
+		my $time;
+		my $n2;
+		my $from;
+		my $to;
+		for($n = 0, $time = $tb; $n < ($tb * $ts); $n++) {
+			$line = @$data[$n];
+			$time = $time - (1 / $ts);
+			printf(" %2d$tc", $time);
+			for($n2 = 0; $n2 < scalar(@APACHE_LIST); $n2++) {
+				undef(@row);
+				$from = $n2 * 5;
+				$to = $from + 5;
+				push(@row, @$line[$from..$to]);
+				printf("   %7d  %9d    %4.2f%%   %3d   %3d", @row);
+			}
+			print("\n");
+		}
+		print("    
\n"); + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; + } + + for($n = 0; $n < scalar(@APACHE_LIST); $n++) { + for($n2 = 1; $n2 <= 3; $n2++) { + $str = $u . $myself . $n . $n2 . "." . $when . ".png"; + push(@PNG, $str); + unlink("$PNG_DIR" . $str); + if($ENABLE_ZOOM eq "Y") { + $str = $u . $myself . $n . $n2 . "z." . $when . ".png"; + push(@PNGz, $str); + unlink("$PNG_DIR" . $str); + } + } + } + + $e = 0; + foreach my $url (@APACHE_LIST) { + if($e) { + print("
\n"); + } + if($title) { + graph_header($title, 2); + } + undef(@riglim); + if($APACHE1_RIGID eq 1) { + push(@riglim, "--upper-limit=$APACHE1_LIMIT"); + } else { + if($APACHE1_RIGID eq 2) { + push(@riglim, "--upper-limit=$APACHE1_LIMIT"); + push(@riglim, "--rigid"); + } + } + if($title) { + print(" \n"); + print(" \n"); + } + undef(@tmp); + undef(@tmpz); + push(@tmp, "AREA:apache" . $e . "_idle#4444EE:Idle"); + push(@tmp, "GPRINT:apache" . $e . "_idle:LAST: Current\\: %3.0lf"); + push(@tmp, "GPRINT:apache" . $e . "_idle:AVERAGE: Average\\: %3.0lf"); + push(@tmp, "GPRINT:apache" . $e . "_idle:MIN: Min\\: %3.0lf"); + push(@tmp, "GPRINT:apache" . $e . "_idle:MAX: Max\\: %3.0lf\\n"); + push(@tmp, "AREA:apache" . $e . "_busy#44EEEE:Busy"); + push(@tmp, "GPRINT:apache" . $e . "_busy:LAST: Current\\: %3.0lf"); + push(@tmp, "GPRINT:apache" . $e . "_busy:AVERAGE: Average\\: %3.0lf"); + push(@tmp, "GPRINT:apache" . $e . "_busy:MIN: Min\\: %3.0lf"); + push(@tmp, "GPRINT:apache" . $e . "_busy:MAX: Max\\: %3.0lf\\n"); + push(@tmp, "LINE1:apache" . $e . "_idle#0000EE"); + push(@tmp, "LINE1:apache" . $e . "_busy#00EEEE"); + push(@tmp, "LINE1:apache" . $e . "_tot#EE0000"); + push(@tmpz, "AREA:apache" . $e . "_idle#4444EE:Idle"); + push(@tmpz, "AREA:apache" . $e . "_busy#44EEEE:Busy"); + push(@tmpz, "LINE2:apache" . $e . "_idle#0000EE"); + push(@tmpz, "LINE2:apache" . $e . "_busy#00EEEE"); + push(@tmpz, "LINE2:apache" . $e . "_tot#EE0000"); + ($width, $height) = split('x', $GRAPH_SIZE{main}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + } + RRDs::graph("$PNG_DIR" . "$PNG[$e * 3]", + "--title=$rgraphs{_apache1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Workers", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:apache" . $e . "_busy=$APACHE_RRD:apache" . $e . "_busy:AVERAGE", + "DEF:apache" . $e . "_idle=$APACHE_RRD:apache" . $e . "_idle:AVERAGE", + "CDEF:apache" . $e . "_tot=apache" . $e . "_busy,apache" . $e . "_idle,+", + "COMMENT: \\n", + @tmp, + "COMMENT: \\n", + "COMMENT: \\n"); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG[$e * 3]: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNGz[$e * 3]", + "--title=$rgraphs{_apache1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Workers", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:apache" . $e . "_busy=$APACHE_RRD:apache" . $e . "_busy:AVERAGE", + "DEF:apache" . $e . "_idle=$APACHE_RRD:apache" . $e . "_idle:AVERAGE", + "CDEF:apache" . $e . "_tot=apache" . $e . "_busy,apache" . $e . "_idle,+", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNGz[$e * 3]: $err\n") if $err; + } + $e2 = $e + 1; + if($title || ($silent =~ /imagetag/ && $graph =~ /apache$e2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + if($title) { + print(" \n"); + print(" \n"); + } + + undef(@riglim); + if($APACHE2_RIGID eq 1) { + push(@riglim, "--upper-limit=$APACHE2_LIMIT"); + } else { + if($APACHE2_RIGID eq 2) { + push(@riglim, "--upper-limit=$APACHE2_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + push(@tmp, "AREA:apache" . $e . "_cpu#44AAEE:CPU"); + push(@tmp, "GPRINT:apache" . $e . "_cpu:LAST: Current\\: %5.2lf%%\\n"); + push(@tmp, "LINE1:apache" . $e . "_cpu#00EEEE"); + push(@tmpz, "AREA:apache" . $e . "_cpu#44AAEE:CPU"); + push(@tmpz, "LINE1:apache" . $e . "_cpu#00EEEE"); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG[$e * 3 + 1]", + "--title=$rgraphs{_apache2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Percent (%)", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:apache" . $e . "_cpu=$APACHE_RRD:apache" . $e . "_cpu:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG[$e * 3 + 1]: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNGz[$e * 3 + 1]", + "--title=$rgraphs{_apache2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Percent", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:apache" . $e . "_cpu=$APACHE_RRD:apache" . $e . "_cpu:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNGz[$e * 3 + 1]: $err\n") if $err; + } + $e2 = $e + 2; + if($title || ($silent =~ /imagetag/ && $graph =~ /apache$e2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@riglim); + if($APACHE3_RIGID eq 1) { + push(@riglim, "--upper-limit=$APACHE3_LIMIT"); + } else { + if($APACHE3_RIGID eq 2) { + push(@riglim, "--upper-limit=$APACHE3_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + push(@tmp, "AREA:apache" . $e . "_acc#44EE44:Accesses"); + push(@tmp, "GPRINT:apache" . $e . "_acc:LAST: Current\\: %5.2lf\\n"); + push(@tmp, "LINE1:apache" . $e . "_acc#00EE00"); + push(@tmpz, "AREA:apache" . $e . "_acc#44EE44:Accesses"); + push(@tmpz, "LINE1:apache" . $e . "_acc#00EE00"); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG[$e * 3 + 2]", + "--title=$rgraphs{_apache3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Accesses/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:apache" . $e . "_acc=$APACHE_RRD:apache" . $e . "_acc:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG[$e * 3 + 2]: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNGz[$e * 3 + 2]", + "--title=$rgraphs{_apache3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Accesses/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:apache" . $e . "_acc=$APACHE_RRD:apache" . $e . "_acc:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNGz[$e * 3 + 2]: $err\n") if $err; + } + $e2 = $e + 3; + if($title || ($silent =~ /imagetag/ && $graph =~ /apache$e2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + if($title) { + print(" \n"); + print(" \n"); + + print(" \n"); + print " \n"; + print " \n"; + print " \n"; + print "   $url\n"; + print " \n"; + print " \n"; + print(" \n"); + graph_footer(); + } + $e++; + } + return 1; +} + +# NGINX graph +# ---------------------------------------------------------------------------- +sub nginx { + my ($myself, $title) = @_; + + my $width; + my $height; + my @riglim; + my @warning; + my @tmp; + my @tmpz; + my @CDEF; + my $T = "B"; + my $vlabel = "bytes/s"; + my $addr; + my $n; + my $err; + + my $PNG1 = $u . $myself . "1." . $when . ".png"; + my $PNG2 = $u . $myself . "2." . $when . ".png"; + my $PNG3 = $u . $myself . "3." . $when . ".png"; + my $PNG1z = $u . $myself . "1z." . $when . ".png"; + my $PNG2z = $u . $myself . "2z." . $when . ".png"; + my $PNG3z = $u . $myself . "3z." . $when . ".png"; + + $title = !$silent ? $title : ""; + + unlink ("$PNG_DIR" . "$PNG1", + "$PNG_DIR" . "$PNG2", + "$PNG_DIR" . "$PNG3"); + if($ENABLE_ZOOM eq "Y") { + unlink ("$PNG_DIR" . "$PNG1z", + "$PNG_DIR" . "$PNG2z", + "$PNG_DIR" . "$PNG3z"); + } + + if($NETSTATS_IN_BPS eq "Y") { + $T = "b"; + $vlabel = "bits/s"; + } + if($IFACE_MODE eq "text") { + if($title) { + graph_header($title, 2); + print(" \n"); + print(" \n"); + } + my (undef, undef, undef, $data) = RRDs::fetch("$NGINX_RRD", + "--start=-$nwhen$twhen", + "AVERAGE", + "-r $res"); + $err = RRDs::error; + print("ERROR: while fetching $NGINX_RRD: $err\n") if $err; + print("
\n");
+		print("Time   Total  Reading  Writing  Waiting Requests   K$T/s_I   K$T/s_O\n");
+		print("------------------------------------------------------------------ \n");
+		my $line;
+		my @row;
+		my $time;
+		for($n = 0, $time = $tb; $n < ($tb * $ts); $n++) {
+			$line = @$data[$n];
+			my ($req, $tot, $rea, $wri, $wai, $ki, $ko) = @$line;
+			$ki /= 1024;
+			$ko /= 1024;
+			if($NETSTATS_IN_BPS eq "Y") {
+				$ki *= 8;
+				$ko *= 8;
+			}
+			@row = ($tot, $rea, $wri, $wai, $req, $ki, $ko);
+			$time = $time - (1 / $ts);
+			printf(" %2d$tc  %6d   %6d   %6d   %6d   %6d   %6d   %6d\n", $time, @row);
+		}
+		print("    
\n"); + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; + } + + if($title) { + graph_header($title, 2); + } + if($NGINX1_RIGID eq 1) { + push(@riglim, "--upper-limit=$NGINX1_LIMIT"); + } else { + if($NGINX1_RIGID eq 2) { + push(@riglim, "--upper-limit=$NGINX1_LIMIT"); + push(@riglim, "--rigid"); + } + } + if($title) { + print(" \n"); + print(" \n"); + } + push(@tmp, "AREA:total#44EEEE:Total"); + push(@tmp, "GPRINT:total:LAST: Current\\: %5.0lf"); + push(@tmp, "GPRINT:total:AVERAGE: Average\\: %5.0lf"); + push(@tmp, "GPRINT:total:MIN: Min\\: %5.0lf"); + push(@tmp, "GPRINT:total:MAX: Max\\: %5.0lf\\n"); + push(@tmp, "AREA:reading#44EE44:Reading"); + push(@tmp, "GPRINT:reading:LAST: Current\\: %5.0lf"); + push(@tmp, "GPRINT:reading:AVERAGE: Average\\: %5.0lf"); + push(@tmp, "GPRINT:reading:MIN: Min\\: %5.0lf"); + push(@tmp, "GPRINT:reading:MAX: Max\\: %5.0lf\\n"); + push(@tmp, "AREA:writing#4444EE:Writing"); + push(@tmp, "GPRINT:writing:LAST: Current\\: %5.0lf"); + push(@tmp, "GPRINT:writing:AVERAGE: Average\\: %5.0lf"); + push(@tmp, "GPRINT:writing:MIN: Min\\: %5.0lf"); + push(@tmp, "GPRINT:writing:MAX: Max\\: %5.0lf\\n"); + push(@tmp, "AREA:waiting#EE44EE:Waiting"); + push(@tmp, "GPRINT:waiting:LAST: Current\\: %5.0lf"); + push(@tmp, "GPRINT:waiting:AVERAGE: Average\\: %5.0lf"); + push(@tmp, "GPRINT:waiting:MIN: Min\\: %5.0lf"); + push(@tmp, "GPRINT:waiting:MAX: Max\\: %5.0lf\\n"); + push(@tmp, "LINE1:total#00EEEE"); + push(@tmp, "LINE1:reading#00EE00"); + push(@tmp, "LINE1:writing#0000EE"); + push(@tmp, "LINE1:waiting#EE00EE"); + push(@tmpz, "AREA:total#44EEEE:Total"); + push(@tmpz, "AREA:reading#44EE44:Reading"); + push(@tmpz, "AREA:writing#4444EE:Writing"); + push(@tmpz, "AREA:waiting#EE44EE:Waiting"); + push(@tmpz, "LINE1:total#00EEEE"); + push(@tmpz, "LINE1:reading#00EE00"); + push(@tmpz, "LINE1:writing#0000EE"); + push(@tmpz, "LINE1:waiting#EE00EE"); + ($width, $height) = split('x', $GRAPH_SIZE{main}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG1", + "--title=$rgraphs{_nginx1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Connections/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:total=$NGINX_RRD:nginx_total:AVERAGE", + "DEF:reading=$NGINX_RRD:nginx_reading:AVERAGE", + "DEF:writing=$NGINX_RRD:nginx_writing:AVERAGE", + "DEF:waiting=$NGINX_RRD:nginx_waiting:AVERAGE", + @tmp, + "COMMENT: \\n"); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG1: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG1z", + "--title=$rgraphs{_nginx1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Connections/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:total=$NGINX_RRD:nginx_total:AVERAGE", + "DEF:reading=$NGINX_RRD:nginx_reading:AVERAGE", + "DEF:writing=$NGINX_RRD:nginx_writing:AVERAGE", + "DEF:waiting=$NGINX_RRD:nginx_waiting:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG1z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /nginx1/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + if($title) { + print(" \n"); + print(" \n"); + } + + undef(@riglim); + if($NGINX2_RIGID eq 1) { + push(@riglim, "--upper-limit=$NGINX2_LIMIT"); + } else { + if($NGINX2_RIGID eq 2) { + push(@riglim, "--upper-limit=$NGINX2_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + push(@tmp, "AREA:requests#44EEEE:Requests"); + push(@tmp, "GPRINT:requests:LAST: Current\\: %5.1lf\\n"); + push(@tmp, "LINE1:requests#00EEEE"); + push(@tmpz, "AREA:requests#44EEEE:Requests"); + push(@tmpz, "LINE1:requests#00EEEE"); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG2", + "--title=$rgraphs{_nginx2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Requests/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:requests=$NGINX_RRD:nginx_requests:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG2: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG2z", + "--title=$rgraphs{_nginx2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Requests/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:requests=$NGINX_RRD:nginx_requests:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG2z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /nginx2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@warning); + if($os eq "Linux") { + open(IN, "netstat -nl --tcp |"); + while() { + (undef, undef, undef, $addr) = split(' ', $_); + chomp($addr); + $addr =~ s/.*://; + if($addr eq $NGINX_PORT) { + last; + } + } + close(IN); + } + if($os eq "FreeBSD" || $os eq "OpenBSD") { + open(IN, "netstat -anl -p tcp |"); + while() { + (undef, undef, undef, $addr, undef, $stat) = split(' ', $_); + chomp($stat); + if($stat eq "LISTEN") { + chomp($addr); + ($addr) = ($addr =~ m/^.*?(\.\d+$)/); + $addr =~ s/\.//; + if($addr eq $NGINX_PORT) { + last; + } + } + } + close(IN); + } + if($addr ne $NGINX_PORT) { + push(@warning, $warning_color); + } + + undef(@riglim); + if($NGINX3_RIGID eq 1) { + push(@riglim, "--upper-limit=$NGINX3_LIMIT"); + } else { + if($NGINX3_RIGID eq 2) { + push(@riglim, "--upper-limit=$NGINX3_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + undef(@CDEF); + push(@tmp, "AREA:B_in#44EE44:Input"); + push(@tmp, "AREA:B_out#4444EE:Output"); + push(@tmp, "AREA:B_out#4444EE:"); + push(@tmp, "AREA:B_in#44EE44:"); + push(@tmp, "LINE1:B_out#0000EE"); + push(@tmp, "LINE1:B_in#00EE00"); + push(@tmpz, "AREA:B_in#44EE44:Input"); + push(@tmpz, "AREA:B_out#4444EE:Output"); + push(@tmpz, "AREA:B_out#4444EE:"); + push(@tmpz, "AREA:B_in#44EE44:"); + push(@tmpz, "LINE1:B_out#0000EE"); + push(@tmpz, "LINE1:B_in#00EE00"); + if($NETSTATS_IN_BPS eq "Y") { + push(@CDEF, "CDEF:B_in=in,8,*"); + push(@CDEF, "CDEF:B_out=out,8,*"); + } else { + push(@CDEF, "CDEF:B_in=in"); + push(@CDEF, "CDEF:B_out=out"); + } + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG3", + "--title=$rgraphs{_nginx3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=$vlabel", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + @warning, + "DEF:in=$NGINX_RRD:nginx_bytes_in:AVERAGE", + "DEF:out=$NGINX_RRD:nginx_bytes_out:AVERAGE", + @CDEF, + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG3: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG3z", + "--title=$rgraphs{_nginx3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=$vlabel", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + @warning, + "DEF:in=$NGINX_RRD:nginx_bytes_in:AVERAGE", + "DEF:out=$NGINX_RRD:nginx_bytes_out:AVERAGE", + @CDEF, + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG3z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /nginx3/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; +} + +# LIGHTTPD graph +# ---------------------------------------------------------------------------- +sub lighttpd { + my ($myself, $title) = @_; + + my $width; + my $height; + my @riglim; + my @PNG; + my @PNGz; + my @tmp; + my @tmpz; + my @CDEF; + my $vlabel = "bytes/s"; + my $e; + my $e2; + my $n; + my $n2; + my $str; + my $err; + + $title = !$silent ? $title : ""; + + if($NETSTATS_IN_BPS eq "Y") { + $vlabel = "bits/s"; + } + if($IFACE_MODE eq "text") { + my $line1; + my $line2; + my $line3; + if($title) { + graph_header($title, 2); + print(" \n"); + print(" \n"); + } + my (undef, undef, undef, $data) = RRDs::fetch("$LIGHTTPD_RRD", + "--start=-$nwhen$twhen", + "AVERAGE", + "-r $res"); + $err = RRDs::error; + print("ERROR: while fetching $LIGHTTPD_RRD: $err\n") if $err; + print("
\n");
+		print("    ");
+		for($n = 0; $n < scalar(@LIGHTTPD_LIST); $n++) {
+			$line1 = "                                    ";
+			$line2 .= "   Acceses     kbytes     Busy  Idle";
+			$line3 .= "------------------------------------";
+			if($line1) {
+				$i = length($line1);
+				printf(sprintf("%${i}s", sprintf("%s", $LIGHTTPD_LIST[$n])));
+			}
+		}
+		print("\n");
+		print("Time$line2\n");
+		print("----$line3 \n");
+		my $line;
+		my @row;
+		my $time;
+		my $n2;
+		my $from;
+		my $to;
+		for($n = 0, $time = $tb; $n < ($tb * $ts); $n++) {
+			$line = @$data[$n];
+			$time = $time - (1 / $ts);
+			printf(" %2d$tc", $time);
+			for($n2 = 0; $n2 < scalar(@LIGHTTPD_LIST); $n2++) {
+				undef(@row);
+				$from = $n2 * 9;
+				$to = $from + 9;
+				push(@row, @$line[$from..$to]);
+				printf("   %7d  %9d      %3d   %3d", @row);
+			}
+			print("\n");
+		}
+		print("    
\n"); + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; + } + + for($n = 0; $n < scalar(@LIGHTTPD_LIST); $n++) { + for($n2 = 1; $n2 <= 3; $n2++) { + $str = $u . $myself . $n . $n2 . "." . $when . ".png"; + push(@PNG, $str); + unlink("$PNG_DIR" . $str); + if($ENABLE_ZOOM eq "Y") { + $str = $u . $myself . $n . $n2 . "z." . $when . ".png"; + push(@PNGz, $str); + unlink("$PNG_DIR" . $str); + } + } + } + + $e = 0; + foreach my $url (@LIGHTTPD_LIST) { + if($e) { + print("
\n"); + } + if($title) { + graph_header($title, 2); + } + undef(@riglim); + if($LIGHTTPD1_RIGID eq 1) { + push(@riglim, "--upper-limit=$LIGHTTPD1_LIMIT"); + } else { + if($LIGHTTPD1_RIGID eq 2) { + push(@riglim, "--upper-limit=$LIGHTTPD1_LIMIT"); + push(@riglim, "--rigid"); + } + } + if($title) { + print(" \n"); + print(" \n"); + } + undef(@tmp); + undef(@tmpz); + push(@tmp, "AREA:lighttpd" . $e . "_idle#4444EE:Idle"); + push(@tmp, "GPRINT:lighttpd" . $e . "_idle:LAST: Current\\: %3.0lf"); + push(@tmp, "GPRINT:lighttpd" . $e . "_idle:AVERAGE: Average\\: %3.0lf"); + push(@tmp, "GPRINT:lighttpd" . $e . "_idle:MIN: Min\\: %3.0lf"); + push(@tmp, "GPRINT:lighttpd" . $e . "_idle:MAX: Max\\: %3.0lf\\n"); + push(@tmp, "AREA:lighttpd" . $e . "_busy#44EEEE:Busy"); + push(@tmp, "GPRINT:lighttpd" . $e . "_busy:LAST: Current\\: %3.0lf"); + push(@tmp, "GPRINT:lighttpd" . $e . "_busy:AVERAGE: Average\\: %3.0lf"); + push(@tmp, "GPRINT:lighttpd" . $e . "_busy:MIN: Min\\: %3.0lf"); + push(@tmp, "GPRINT:lighttpd" . $e . "_busy:MAX: Max\\: %3.0lf\\n"); + push(@tmp, "LINE1:lighttpd" . $e . "_idle#0000EE"); + push(@tmp, "LINE1:lighttpd" . $e . "_busy#00EEEE"); + push(@tmp, "LINE1:lighttpd" . $e . "_tot#EE0000"); + push(@tmpz, "AREA:lighttpd" . $e . "_idle#4444EE:Idle"); + push(@tmpz, "AREA:lighttpd" . $e . "_busy#44EEEE:Busy"); + push(@tmpz, "LINE2:lighttpd" . $e . "_idle#0000EE"); + push(@tmpz, "LINE2:lighttpd" . $e . "_busy#00EEEE"); + push(@tmpz, "LINE2:lighttpd" . $e . "_tot#EE0000"); + ($width, $height) = split('x', $GRAPH_SIZE{main}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + } + RRDs::graph("$PNG_DIR" . "$PNG[$e * 3]", + "--title=$rgraphs{_lighttpd1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Workers", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:lighttpd" . $e . "_busy=$LIGHTTPD_RRD:lighttpd" . $e . "_busy:AVERAGE", + "DEF:lighttpd" . $e . "_idle=$LIGHTTPD_RRD:lighttpd" . $e . "_idle:AVERAGE", + "CDEF:lighttpd" . $e . "_tot=lighttpd" . $e . "_busy,lighttpd" . $e . "_idle,+", + "COMMENT: \\n", + @tmp, + "COMMENT: \\n", + "COMMENT: \\n"); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG[$e * 3]: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNGz[$e * 3]", + "--title=$rgraphs{_lighttpd1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Workers", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:lighttpd" . $e . "_busy=$LIGHTTPD_RRD:lighttpd" . $e . "_busy:AVERAGE", + "DEF:lighttpd" . $e . "_idle=$LIGHTTPD_RRD:lighttpd" . $e . "_idle:AVERAGE", + "CDEF:lighttpd" . $e . "_tot=lighttpd" . $e . "_busy,lighttpd" . $e . "_idle,+", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNGz[$e * 3]: $err\n") if $err; + } + $e2 = $e + 1; + if($title || ($silent =~ /imagetag/ && $graph =~ /lighttpd$e2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + if($title) { + print(" \n"); + print(" \n"); + } + + undef(@riglim); + if($LIGHTTPD2_RIGID eq 1) { + push(@riglim, "--upper-limit=$LIGHTTPD2_LIMIT"); + } else { + if($LIGHTTPD2_RIGID eq 2) { + push(@riglim, "--upper-limit=$LIGHTTPD2_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + undef(@CDEF); + push(@tmp, "AREA:Bytes#44AAEE:KBytes"); + push(@tmp, "GPRINT:lighttpd" . $e . "_kb:LAST: Current\\: %6.1lf\\n"); + push(@tmp, "LINE1:lighttpd" . $e . "_kb#00EEEE"); + push(@tmpz, "AREA:Bytes#44AAEE:Bytes"); + push(@tmpz, "LINE1:lighttpd" . $e . "_kb#00EEEE"); + if($NETSTATS_IN_BPS eq "Y") { + push(@CDEF, "CDEF:Bytes=lighttpd" . $e . "_kb,8,*,1024,*"); + } else { + push(@CDEF, "CDEF:Bytes=lighttpd" . $e . "_kb,1024,*"); + } + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG[$e * 3 + 1]", + "--title=$rgraphs{_lighttpd2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=$vlabel", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:lighttpd" . $e . "_kb=$LIGHTTPD_RRD:lighttpd" . $e . "_kb:AVERAGE", + @CDEF, + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG[$e * 3 + 1]: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNGz[$e * 3 + 1]", + "--title=$rgraphs{_lighttpd2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=$vlabel", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:lighttpd" . $e . "_kb=$LIGHTTPD_RRD:lighttpd" . $e . "_kb:AVERAGE", + @CDEF, + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNGz[$e * 3 + 1]: $err\n") if $err; + } + $e2 = $e + 2; + if($title || ($silent =~ /imagetag/ && $graph =~ /lighttpd$e2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@riglim); + if($LIGHTTPD3_RIGID eq 1) { + push(@riglim, "--upper-limit=$LIGHTTPD3_LIMIT"); + } else { + if($LIGHTTPD3_RIGID eq 2) { + push(@riglim, "--upper-limit=$LIGHTTPD3_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + push(@tmp, "AREA:lighttpd" . $e . "_acc#44EE44:Accesses"); + push(@tmp, "GPRINT:lighttpd" . $e . "_acc:LAST: Current\\: %5.2lf\\n"); + push(@tmp, "LINE1:lighttpd" . $e . "_acc#00EE00"); + push(@tmpz, "AREA:lighttpd" . $e . "_acc#44EE44:Accesses"); + push(@tmpz, "LINE1:lighttpd" . $e . "_acc#00EE00"); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG[$e * 3 + 2]", + "--title=$rgraphs{_lighttpd3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Accesses/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:lighttpd" . $e . "_acc=$LIGHTTPD_RRD:lighttpd" . $e . "_acc:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG[$e * 3 + 2]: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNGz[$e * 3 + 2]", + "--title=$rgraphs{_lighttpd3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Accesses/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:lighttpd" . $e . "_acc=$LIGHTTPD_RRD:lighttpd" . $e . "_acc:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNGz[$e * 3 + 2]: $err\n") if $err; + } + $e2 = $e + 3; + if($title || ($silent =~ /imagetag/ && $graph =~ /lighttpd$e2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + if($title) { + print(" \n"); + print(" \n"); + + print(" \n"); + print " \n"; + print " \n"; + print " \n"; + print "   $url\n"; + print " \n"; + print " \n"; + print(" \n"); + graph_footer(); + } + $e++; + } + return 1; +} + +# MYSQL graph +# ---------------------------------------------------------------------------- +sub mysql { + my ($myself, $title) = @_; + + my $width; + my $height; + my @riglim; + my @PNG; + my @PNGz; + my @tmp; + my @tmpz; + my @CDEF; + my $T = "B"; + my $vlabel = "bytes/s"; + my $e; + my $e2; + my $n; + my $n2; + my $num; + my $err; + + $title = !$silent ? $title : ""; + + if($NETSTATS_IN_BPS eq "Y") { + $T = "b"; + $vlabel = "bits/s"; + } + $MYSQL_CONN_TYPE = $MYSQL_CONN_TYPE || "Host"; + if(lc($MYSQL_CONN_TYPE) eq "host") { + $num = scalar(@MYSQL_HOST_LIST); + } + if(lc($MYSQL_CONN_TYPE) eq "socket") { + $num = scalar(@MYSQL_SOCK_LIST); + } + if($IFACE_MODE eq "text") { + my $line1; + my $line2; + my $line3; + if($title) { + graph_header($title, 2); + print(" \n"); + print(" \n"); + } + my (undef, undef, undef, $data) = RRDs::fetch("$MYSQL_RRD", + "--start=-$nwhen$twhen", + "AVERAGE", + "-r $res"); + $err = RRDs::error; + print("ERROR: while fetching $MYSQL_RRD: $err\n") if $err; + print("
\n");
+		print("    ");
+		for($n = 0; $n < $num; $n++) {
+			$line1 = "                                                                                                                                                                                                                          ";
+			$line2 .= "   Select  Commit  Delete  Insert  Insert_S  Update  Replace  Replace_S  Rollback  TCacheHit  QCache_U  Conns_U  KeyBuf_U  InnoDB_U  OpenedTbl  TLocks_W  Queries  SlowQrs  Conns  AbrtCli  AbrtConn  BytesRecv  BytesSent";
+			$line3 .= "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------";
+			if($line1) {
+				$i = length($line1);
+				if(lc($MYSQL_CONN_TYPE) eq "host") {
+					printf(sprintf("%${i}s", sprintf("%s:%s", $MYSQL_HOST_LIST[$n], $MYSQL_PORT_LIST[$n])));
+				}
+				if(lc($MYSQL_CONN_TYPE) eq "socket") {
+					printf(sprintf("%${i}s", sprintf("socket: %s", $MYSQL_SOCK_LIST[$n])));
+				}
+			}
+		}
+		print("\n");
+		print("Time$line2\n");
+		print("----$line3 \n");
+		my $line;
+		my @row;
+		my $time;
+		my $n2;
+		my $from;
+		my $to;
+		for($n = 0, $time = $tb; $n < ($tb * $ts); $n++) {
+			$line = @$data[$n];
+			$time = $time - (1 / $ts);
+			printf(" %2d$tc", $time);
+			for($n2 = 0; $n2 < $num; $n2++) {
+				undef(@row);
+				$from = $n2 * 38;
+				$to = $from + 38;
+				push(@row, @$line[$from..$to]);
+				printf("   %6d  %6d  %6d  %6d  %8d  %6d  %7d   %8d  %8d        %2d%%       %2d%%      %2d%%       %2d%%       %2d%%     %6d    %6d   %6d   %6d %6d   %6d    %6d  %9d  %9d", @row);
+			}
+			print("\n");
+		}
+		print("    
\n"); + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; + } + + $e = 0; + for($n = 0; $n < $num; $n++) { + for($n2 = 1; $n2 <= 6; $n2++) { + $str = $u . $myself . $n . $n2 . "." . $when . ".png"; + push(@PNG, $str); + unlink("$PNG_DIR" . $str); + if($ENABLE_ZOOM eq "Y") { + $str = $u . $myself . $n . $n2 . "z." . $when . ".png"; + push(@PNGz, $str); + unlink("$PNG_DIR" . $str); + } + } + + if(lc($MYSQL_CONN_TYPE) eq "host") { + $str = $MYSQL_HOST_LIST[$e] . ":" . $MYSQL_PORT_LIST[$e]; + } + if(lc($MYSQL_CONN_TYPE) eq "socket") { + $str = "socket: " . $MYSQL_SOCK_LIST[$e]; + } + + if($e) { + print("
\n"); + } + if($title) { + graph_header($title, 2); + } + undef(@riglim); + if($MYSQL1_RIGID eq 1) { + push(@riglim, "--upper-limit=$MYSQL1_LIMIT"); + } else { + if($MYSQL1_RIGID eq 2) { + push(@riglim, "--upper-limit=$MYSQL1_LIMIT"); + push(@riglim, "--rigid"); + } + } + if($title) { + print(" \n"); + print(" \n"); + } + undef(@tmp); + undef(@tmpz); + push(@tmp, "LINE1:com_select#FFA500:Select"); + push(@tmp, "GPRINT:com_select:LAST: Cur\\: %6.1lf"); + push(@tmp, "GPRINT:com_select:AVERAGE: Avg\\: %6.1lf"); + push(@tmp, "GPRINT:com_select:MIN: Min\\: %6.1lf"); + push(@tmp, "GPRINT:com_select:MAX: Max\\: %6.1lf\\n"); + push(@tmp, "LINE1:com_commit#EEEE44:Commit"); + push(@tmp, "GPRINT:com_commit:LAST: Cur\\: %6.1lf"); + push(@tmp, "GPRINT:com_commit:AVERAGE: Avg\\: %6.1lf"); + push(@tmp, "GPRINT:com_commit:MIN: Min\\: %6.1lf"); + push(@tmp, "GPRINT:com_commit:MAX: Max\\: %6.1lf\\n"); + push(@tmp, "LINE1:com_delete#EE4444:Delete"); + push(@tmp, "GPRINT:com_delete:LAST: Cur\\: %6.1lf"); + push(@tmp, "GPRINT:com_delete:AVERAGE: Avg\\: %6.1lf"); + push(@tmp, "GPRINT:com_delete:MIN: Min\\: %6.1lf"); + push(@tmp, "GPRINT:com_delete:MAX: Max\\: %6.1lf\\n"); + push(@tmp, "LINE1:com_insert#44EE44:Insert"); + push(@tmp, "GPRINT:com_insert:LAST: Cur\\: %6.1lf"); + push(@tmp, "GPRINT:com_insert:AVERAGE: Avg\\: %6.1lf"); + push(@tmp, "GPRINT:com_insert:MIN: Min\\: %6.1lf"); + push(@tmp, "GPRINT:com_insert:MAX: Max\\: %6.1lf\\n"); + push(@tmp, "LINE1:com_insert_s#448844:Insert Select"); + push(@tmp, "GPRINT:com_insert_s:LAST: Cur\\: %6.1lf"); + push(@tmp, "GPRINT:com_insert_s:AVERAGE: Avg\\: %6.1lf"); + push(@tmp, "GPRINT:com_insert_s:MIN: Min\\: %6.1lf"); + push(@tmp, "GPRINT:com_insert_s:MAX: Max\\: %6.1lf\\n"); + push(@tmp, "LINE1:com_update#EE44EE:Update"); + push(@tmp, "GPRINT:com_update:LAST: Cur\\: %6.1lf"); + push(@tmp, "GPRINT:com_update:AVERAGE: Avg\\: %6.1lf"); + push(@tmp, "GPRINT:com_update:MIN: Min\\: %6.1lf"); + push(@tmp, "GPRINT:com_update:MAX: Max\\: %6.1lf\\n"); + push(@tmp, "LINE1:com_replace#44EEEE:Replace"); + push(@tmp, "GPRINT:com_replace:LAST: Cur\\: %6.1lf"); + push(@tmp, "GPRINT:com_replace:AVERAGE: Avg\\: %6.1lf"); + push(@tmp, "GPRINT:com_replace:MIN: Min\\: %6.1lf"); + push(@tmp, "GPRINT:com_replace:MAX: Max\\: %6.1lf\\n"); + push(@tmp, "LINE1:com_replace_s#4444EE:Replace Select"); + push(@tmp, "GPRINT:com_replace_s:LAST: Cur\\: %6.1lf"); + push(@tmp, "GPRINT:com_replace_s:AVERAGE: Avg\\: %6.1lf"); + push(@tmp, "GPRINT:com_replace_s:MIN: Min\\: %6.1lf"); + push(@tmp, "GPRINT:com_replace_s:MAX: Max\\: %6.1lf\\n"); + push(@tmp, "LINE1:com_rollback#444444:Rollback"); + push(@tmp, "GPRINT:com_rollback:LAST: Cur\\: %6.1lf"); + push(@tmp, "GPRINT:com_rollback:AVERAGE: Avg\\: %6.1lf"); + push(@tmp, "GPRINT:com_rollback:MIN: Min\\: %6.1lf"); + push(@tmp, "GPRINT:com_rollback:MAX: Max\\: %6.1lf\\n"); + push(@tmpz, "LINE2:com_select#FFA500:Select"); + push(@tmpz, "LINE2:com_commit#EEEE44:Commit"); + push(@tmpz, "LINE2:com_delete#EE4444:Delete"); + push(@tmpz, "LINE2:com_insert#44EE44:Insert"); + push(@tmpz, "LINE2:com_insert_s#448844:Insert Sel"); + push(@tmpz, "LINE2:com_update#EE44EE:Update"); + push(@tmpz, "LINE2:com_replace#44EEEE:Replace"); + push(@tmpz, "LINE2:com_replace_s#4444EE:Replace Sel"); + push(@tmpz, "LINE2:com_rollback#444444:Rollback"); + ($width, $height) = split('x', $GRAPH_SIZE{main}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG[$e * 6]", + "--title=$rgraphs{_mysql1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Queries/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:com_select=$MYSQL_RRD:mysql" . $e . "_csel:AVERAGE", + "DEF:com_commit=$MYSQL_RRD:mysql" . $e . "_ccom:AVERAGE", + "DEF:com_delete=$MYSQL_RRD:mysql" . $e . "_cdel:AVERAGE", + "DEF:com_insert=$MYSQL_RRD:mysql" . $e . "_cins:AVERAGE", + "DEF:com_insert_s=$MYSQL_RRD:mysql" . $e . "_cinss:AVERAGE", + "DEF:com_update=$MYSQL_RRD:mysql" . $e . "_cupd:AVERAGE", + "DEF:com_replace=$MYSQL_RRD:mysql" . $e . "_crep:AVERAGE", + "DEF:com_replace_s=$MYSQL_RRD:mysql" . $e . "_creps:AVERAGE", + "DEF:com_rollback=$MYSQL_RRD:mysql" . $e . "_crol:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG[$e * 6]: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNGz[$e * 6]", + "--title=$rgraphs{_mysql1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Queries/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:com_select=$MYSQL_RRD:mysql" . $e . "_csel:AVERAGE", + "DEF:com_commit=$MYSQL_RRD:mysql" . $e . "_ccom:AVERAGE", + "DEF:com_delete=$MYSQL_RRD:mysql" . $e . "_cdel:AVERAGE", + "DEF:com_insert=$MYSQL_RRD:mysql" . $e . "_cins:AVERAGE", + "DEF:com_insert_s=$MYSQL_RRD:mysql" . $e . "_cinss:AVERAGE", + "DEF:com_update=$MYSQL_RRD:mysql" . $e . "_cupd:AVERAGE", + "DEF:com_replace=$MYSQL_RRD:mysql" . $e . "_crep:AVERAGE", + "DEF:com_replace_s=$MYSQL_RRD:mysql" . $e . "_creps:AVERAGE", + "DEF:com_rollback=$MYSQL_RRD:mysql" . $e . "_crol:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNGz[$e * 6]: $err\n") if $err; + } + $e2 = $e + 1; + if($title || ($silent =~ /imagetag/ && $graph =~ /mysql$e2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@riglim); + if($MYSQL2_RIGID eq 1) { + push(@riglim, "--upper-limit=$MYSQL2_LIMIT"); + } else { + if($MYSQL2_RIGID eq 2) { + push(@riglim, "--upper-limit=$MYSQL2_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + push(@tmp, "LINE1:tcache_hit_r#FFA500:Thread Cache Hit Rate"); + push(@tmp, "GPRINT:tcache_hit_r:LAST: Cur\\: %4.1lf%%"); + push(@tmp, "GPRINT:tcache_hit_r:AVERAGE: Avg\\: %4.1lf%%"); + push(@tmp, "GPRINT:tcache_hit_r:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:tcache_hit_r:MAX: Max\\: %4.1lf%%\\n"); + push(@tmp, "LINE1:qcache_usage#44EEEE:Query Cache Usage"); + push(@tmp, "GPRINT:qcache_usage:LAST: Cur\\: %4.1lf%%"); + push(@tmp, "GPRINT:qcache_usage:AVERAGE: Avg\\: %4.1lf%%"); + push(@tmp, "GPRINT:qcache_usage:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:qcache_usage:MAX: Max\\: %4.1lf%%\\n"); + push(@tmp, "LINE1:conns_u#44EE44:Connections Usage"); + push(@tmp, "GPRINT:conns_u:LAST: Cur\\: %4.1lf%%"); + push(@tmp, "GPRINT:conns_u:AVERAGE: Avg\\: %4.1lf%%"); + push(@tmp, "GPRINT:conns_u:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:conns_u:MAX: Max\\: %4.1lf%%\\n"); + push(@tmp, "LINE1:key_buf_u#EE4444:Key Buffer Usage"); + push(@tmp, "GPRINT:key_buf_u:LAST: Cur\\: %4.1lf%%"); + push(@tmp, "GPRINT:key_buf_u:AVERAGE: Avg\\: %4.1lf%%"); + push(@tmp, "GPRINT:key_buf_u:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:key_buf_u:MAX: Max\\: %4.1lf%%\\n"); + push(@tmp, "LINE1:innodb_buf_u#EE44EE:InnoDB Buffer P. Usage"); + push(@tmp, "GPRINT:innodb_buf_u:LAST: Cur\\: %4.1lf%%"); + push(@tmp, "GPRINT:innodb_buf_u:AVERAGE: Avg\\: %4.1lf%%"); + push(@tmp, "GPRINT:innodb_buf_u:MIN: Min\\: %4.1lf%%"); + push(@tmp, "GPRINT:innodb_buf_u:MAX: Max\\: %4.1lf%%\\n"); + push(@tmpz, "LINE2:tcache_hit_r#FFA500:Thread Cache Hit Rate"); + push(@tmpz, "LINE2:qcache_usage#44EEEE:Query Cache Usage"); + push(@tmpz, "LINE2:conns_u#44EE44:Connections Usage"); + push(@tmpz, "LINE2:key_buf_u#EE4444:Key Buffer Usage"); + push(@tmpz, "LINE2:innodb_buf_u#EE44EE:Innodb Buffer P. Usage"); + ($width, $height) = split('x', $GRAPH_SIZE{main}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG[$e * 6 + 1]", + "--title=$rgraphs{_mysql2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Percent (%)", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:tcache_hit_r=$MYSQL_RRD:mysql" . $e . "_tchr:AVERAGE", + "DEF:qcache_usage=$MYSQL_RRD:mysql" . $e . "_qcu:AVERAGE", + "DEF:conns_u=$MYSQL_RRD:mysql" . $e . "_conns_u:AVERAGE", + "DEF:key_buf_u=$MYSQL_RRD:mysql" . $e . "_kbu:AVERAGE", + "DEF:innodb_buf_u=$MYSQL_RRD:mysql" . $e . "_innbu:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG[$e * 6 + 1]: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNGz[$e * 6 + 1]", + "--title=$rgraphs{_mysql2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Percent (%)", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:tcache_hit_r=$MYSQL_RRD:mysql" . $e . "_tchr:AVERAGE", + "DEF:qcache_usage=$MYSQL_RRD:mysql" . $e . "_qcu:AVERAGE", + "DEF:conns_u=$MYSQL_RRD:mysql" . $e . "_conns_u:AVERAGE", + "DEF:key_buf_u=$MYSQL_RRD:mysql" . $e . "_kbu:AVERAGE", + "DEF:innodb_buf_u=$MYSQL_RRD:mysql" . $e . "_innbu:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNGz[$e * 6 + 1]: $err\n") if $err; + } + $e2 = $e + 2; + if($title || ($silent =~ /imagetag/ && $graph =~ /mysql$e2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + if($title) { + print(" \n"); + print(" \n"); + } + + undef(@riglim); + if($MYSQL3_RIGID eq 1) { + push(@riglim, "--upper-limit=$MYSQL3_LIMIT"); + } else { + if($MYSQL3_RIGID eq 2) { + push(@riglim, "--upper-limit=$MYSQL3_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + push(@tmp, "AREA:opened_tbl#44EEEE:Opened Tables"); + push(@tmp, "GPRINT:opened_tbl:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "AREA:tlocks_w#4444EE:Table Locks Waited"); + push(@tmp, "GPRINT:tlocks_w:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "LINE1:opened_tbl#00EEEE"); + push(@tmp, "LINE1:tlocks_w#0000EE"); + push(@tmpz, "AREA:opened_tbl#44EEEE:Opened Tables"); + push(@tmpz, "AREA:tlocks_w#4444EE:Table Locks Waited"); + push(@tmpz, "LINE1:opened_tbl#00EEEE"); + push(@tmpz, "LINE1:tlocks_w#0000EE"); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG[$e * 6 + 2]", + "--title=$rgraphs{_mysql3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Open & Locks/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:opened_tbl=$MYSQL_RRD:mysql" . $e . "_ot:AVERAGE", + "DEF:tlocks_w=$MYSQL_RRD:mysql" . $e . "_tlw:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG[$e * 6 + 2]: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNGz[$e * 6 + 2]", + "--title=$rgraphs{_mysql3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Open & Locks/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:opened_tbl=$MYSQL_RRD:mysql" . $e . "_ot:AVERAGE", + "DEF:tlocks_w=$MYSQL_RRD:mysql" . $e . "_tlw:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNGz[$e * 6 + 2]: $err\n") if $err; + } + $e2 = $e + 3; + if($title || ($silent =~ /imagetag/ && $graph =~ /mysql$e2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@riglim); + if($MYSQL4_RIGID eq 1) { + push(@riglim, "--upper-limit=$MYSQL4_LIMIT"); + } else { + if($MYSQL4_RIGID eq 2) { + push(@riglim, "--upper-limit=$MYSQL4_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + push(@tmp, "AREA:qrs#44EEEE:Queries"); + push(@tmp, "GPRINT:qrs:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "AREA:sqrs#4444EE:Slow Queries"); + push(@tmp, "GPRINT:sqrs:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "LINE1:qrs#00EEEE"); + push(@tmp, "LINE1:sqrs#0000EE"); + push(@tmpz, "AREA:qrs#44EEEE:Queries"); + push(@tmpz, "AREA:sqrs#4444EE:Slow Queries"); + push(@tmpz, "LINE1:qrs#00EEEE"); + push(@tmpz, "LINE1:sqrs#0000EE"); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG[$e * 6 + 3]", + "--title=$rgraphs{_mysql4} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Queries/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:qrs=$MYSQL_RRD:mysql" . $e . "_queries:AVERAGE", + "DEF:sqrs=$MYSQL_RRD:mysql" . $e . "_sq:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG[$e * 6 + 3]: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNGz[$e * 6 + 3]", + "--title=$rgraphs{_mysql4} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Queries/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:qrs=$MYSQL_RRD:mysql" . $e . "_queries:AVERAGE", + "DEF:sqrs=$MYSQL_RRD:mysql" . $e . "_sq:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNGz[$e * 6 + 3]: $err\n") if $err; + } + $e2 = $e + 4; + if($title || ($silent =~ /imagetag/ && $graph =~ /mysql$e2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@riglim); + if($MYSQL5_RIGID eq 1) { + push(@riglim, "--upper-limit=$MYSQL5_LIMIT"); + } else { + if($MYSQL5_RIGID eq 2) { + push(@riglim, "--upper-limit=$MYSQL5_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + push(@tmp, "AREA:conns#44EEEE:Connections"); + push(@tmp, "GPRINT:conns:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "AREA:acli#EEEE44:Aborted Clients"); + push(@tmp, "GPRINT:acli:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "AREA:acon#EE4444:Aborted Connects"); + push(@tmp, "GPRINT:acon:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "LINE1:conns#00EEEE"); + push(@tmp, "LINE1:acli#EEEE00"); + push(@tmp, "LINE1:acon#EE0000"); + push(@tmpz, "AREA:conns#44EEEE:Connections"); + push(@tmpz, "AREA:acli#EEEE44:Aborted Clients"); + push(@tmpz, "AREA:acon#EE4444:Aborted Connects"); + push(@tmpz, "LINE1:conns#00EEEE"); + push(@tmpz, "LINE1:acli#EEEE00"); + push(@tmpz, "LINE1:acon#EE0000"); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG[$e * 6 + 4]", + "--title=$rgraphs{_mysql5} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Connectionss/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:conns=$MYSQL_RRD:mysql" . $e . "_conns:AVERAGE", + "DEF:acli=$MYSQL_RRD:mysql" . $e . "_acli:AVERAGE", + "DEF:acon=$MYSQL_RRD:mysql" . $e . "_acon:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG[$e * 6 + 4]: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNGz[$e * 6 + 4]", + "--title=$rgraphs{_mysql5} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Connectionss/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:conns=$MYSQL_RRD:mysql" . $e . "_conns:AVERAGE", + "DEF:acli=$MYSQL_RRD:mysql" . $e . "_acli:AVERAGE", + "DEF:acon=$MYSQL_RRD:mysql" . $e . "_acon:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNGz[$e * 6 + 4]: $err\n") if $err; + } + $e2 = $e + 5; + if($title || ($silent =~ /imagetag/ && $graph =~ /mysql$e2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@riglim); + if($MYSQL6_RIGID eq 1) { + push(@riglim, "--upper-limit=$MYSQL6_LIMIT"); + } else { + if($MYSQL6_RIGID eq 2) { + push(@riglim, "--upper-limit=$MYSQL6_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + undef(@CDEF); + push(@tmp, "AREA:B_in#44EE44:Input"); + push(@tmp, "AREA:B_out#4444EE:Output"); + push(@tmp, "AREA:B_out#4444EE:"); + push(@tmp, "AREA:B_in#44EE44:"); + push(@tmp, "LINE1:B_out#0000EE"); + push(@tmp, "LINE1:B_in#00EE00"); + push(@tmpz, "AREA:B_in#44EE44:Input"); + push(@tmpz, "AREA:B_out#4444EE:Output"); + push(@tmpz, "AREA:B_out#4444EE:"); + push(@tmpz, "AREA:B_in#44EE44:"); + push(@tmpz, "LINE1:B_out#0000EE"); + push(@tmpz, "LINE1:B_in#00EE00"); + if($NETSTATS_IN_BPS eq "Y") { + push(@CDEF, "CDEF:B_in=in,8,*"); + push(@CDEF, "CDEF:B_out=out,8,*"); + } else { + push(@CDEF, "CDEF:B_in=in"); + push(@CDEF, "CDEF:B_out=out"); + } + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG[$e * 6 + 5]", + "--title=$rgraphs{_mysql6} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=$vlabel", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:in=$MYSQL_RRD:mysql" . $e . "_brecv:AVERAGE", + "DEF:out=$MYSQL_RRD:mysql" . $e . "_bsent:AVERAGE", + @CDEF, + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG[$e * 6 + 5]: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNGz[$e * 6 + 5]", + "--title=$rgraphs{_mysql6} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=$vlabel", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:in=$MYSQL_RRD:mysql" . $e . "_brecv:AVERAGE", + "DEF:out=$MYSQL_RRD:mysql" . $e . "_bsent:AVERAGE", + @CDEF, + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNGz[$e * 6 + 5]: $err\n") if $err; + } + $e2 = $e + 6; + if($title || ($silent =~ /imagetag/ && $graph =~ /mysql$e2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + if($title) { + print(" \n"); + print(" \n"); + + print(" \n"); + print " \n"; + print " \n"; + print " \n"; + print "   $str\n"; + print " \n"; + print " \n"; + print(" \n"); + graph_footer(); + } + $e++; + } + return 1; +} + +# SQUID graph +# ---------------------------------------------------------------------------- +sub squid { + my ($myself, $title) = @_; + + my $width; + my $height; + my @riglim; + my @tmp; + my @tmpz; + my $i; + my @DEF; + my $n; + my $str; + my $err; + my @AC = ( + "#FFA500", + "#44EEEE", + "#44EE44", + "#4444EE", + "#448844", + "#EE4444", + "#EE44EE", + "#EEEE44", + "#963C74", + "#CCCCCC", + ); + my @LC = ( + "#FFA500", + "#00EEEE", + "#00EE00", + "#0000EE", + "#448844", + "#EE0000", + "#EE00EE", + "#EEEE00", + "#B4B444", + "#888888", + ); + + my $PNG1 = $u . $myself . "1." . $when . ".png"; + my $PNG2 = $u . $myself . "2." . $when . ".png"; + my $PNG3 = $u . $myself . "3." . $when . ".png"; + my $PNG4 = $u . $myself . "4." . $when . ".png"; + my $PNG5 = $u . $myself . "5." . $when . ".png"; + my $PNG6 = $u . $myself . "6." . $when . ".png"; + my $PNG7 = $u . $myself . "7." . $when . ".png"; + my $PNG8 = $u . $myself . "8." . $when . ".png"; + my $PNG9 = $u . $myself . "9." . $when . ".png"; + my $PNG1z = $u . $myself . "1z." . $when . ".png"; + my $PNG2z = $u . $myself . "2z." . $when . ".png"; + my $PNG3z = $u . $myself . "3z." . $when . ".png"; + my $PNG4z = $u . $myself . "4z." . $when . ".png"; + my $PNG5z = $u . $myself . "5z." . $when . ".png"; + my $PNG6z = $u . $myself . "6z." . $when . ".png"; + my $PNG7z = $u . $myself . "7z." . $when . ".png"; + my $PNG8z = $u . $myself . "8z." . $when . ".png"; + my $PNG9z = $u . $myself . "9z." . $when . ".png"; + + $title = !$silent ? $title : ""; + + unlink ("$PNG_DIR" . "$PNG1", + "$PNG_DIR" . "$PNG2", + "$PNG_DIR" . "$PNG3", + "$PNG_DIR" . "$PNG4", + "$PNG_DIR" . "$PNG5", + "$PNG_DIR" . "$PNG6", + "$PNG_DIR" . "$PNG7", + "$PNG_DIR" . "$PNG8", + "$PNG_DIR" . "$PNG9"); + if($ENABLE_ZOOM eq "Y") { + unlink ("$PNG_DIR" . "$PNG1z", + "$PNG_DIR" . "$PNG2z", + "$PNG_DIR" . "$PNG3z", + "$PNG_DIR" . "$PNG4z", + "$PNG_DIR" . "$PNG5z", + "$PNG_DIR" . "$PNG6z", + "$PNG_DIR" . "$PNG7z", + "$PNG_DIR" . "$PNG8z", + "$PNG_DIR" . "$PNG9z"); + } + + if($IFACE_MODE eq "text") { + if($title) { + graph_header($title, 2); + print(" \n"); + print(" \n"); + } + my (undef, undef, undef, $data) = RRDs::fetch("$SQUID_RRD", + "--start=-$nwhen$twhen", + "AVERAGE", + "-r $res"); + $err = RRDs::error; + print("ERROR: while fetching $SQUID_RRD: $err\n") if $err; + my $str; + my $line1; + my $line2; + my $line3; + print("
\n");
+		for($n = 0; $n < scalar(@SQUID_GRAPH_1); $n++) {
+			$line2 .= sprintf("%6d", $n + 1);
+			$str .= "------";
+		}
+		$line3 .= $str;
+		$i = length($str);
+		$line1 .= sprintf(" %${i}s", "Statistics graph 1");
+		undef($str);
+		$line2 .= " ";
+		$line3 .= "-";
+		for($n = 0; $n < scalar(@SQUID_GRAPH_2); $n++) {
+			$line2 .= sprintf("%6d", $n + 1);
+			$str .= "------";
+		}
+		$line3 .= $str;
+		$i = length($str);
+		$line1 .= sprintf(" %${i}s", "Statistics graph 2");
+		$line1 .= "                                              Overall I/O";
+		$line2 .= "  cHTTPr cHTTPh sHTTPr  sFTPr sOther Abortr SwpFcl Unlnkr";
+		$line3 .= "---------------------------------------------------------";
+		$line1 .= "     Memory usage (MB)";
+		$line2 .= "   Alloct   InUse  %  ";
+		$line3 .= "----------------------";
+		$line1 .= "      Storage usage (MB)";
+		$line2 .= "    Alloct    InUse  %  ";
+		$line3 .= "------------------------";
+		$line1 .= "        IP Cache";
+		$line2 .= "  Reqs Hits Miss";
+		$line3 .= "----------------";
+		$line1 .= "    Network Protocols";
+		$line2 .= "  HTTP  FTP Goph WAIS";
+		$line3 .= "---------------------";
+		$line1 .= "  Client Traffic";
+		$line2 .= "    Input Output";
+		$line3 .= "----------------";
+		$line1 .= "  Server Traffic";
+		$line2 .= "    Input Output";
+		$line3 .= "----------------";
+		print("    $line1\n");
+		print("Time $line2\n");
+		print("-----$line3 \n");
+		my $line;
+		my @row;
+		my $time;
+		my @g1;
+		my @g2;
+		my $n2;
+		for($n = 0, $time = $tb; $n < ($tb * $ts); $n++) {
+			$line = @$data[$n];
+			undef($line1);
+			undef(@row);
+			(@g1) = @$line[0..scalar(@SQUID_GRAPH_1) - 1];
+			for($n2 = 0; $n2 < scalar(@SQUID_GRAPH_1); $n2++) {
+				push(@row, $g1[$n2]);
+				$line1 .= "%5d ";
+			}
+			(@g2) = @$line[9..9 + scalar(@SQUID_GRAPH_2) - 1];
+			$line1 .= " ";
+			for($n2 = 0; $n2 < scalar(@SQUID_GRAPH_2); $n2++) {
+				push(@row, $g2[$n2]);
+				$line1 .= "%5d ";
+			}
+			$line1 .= " ";
+			push(@row, @$line[18..25]);
+			$line1 .= "%6d %6d %6d %6d %6d %6d %6d %6d ";
+			$line1 .= " ";
+			push(@row, @$line[27..28]);
+			push(@row, (@$line[28] * 100) / @$line[27]);
+			$line1 .= "%7d %7d %3.1f ";
+			$line1 .= " ";
+			push(@row, @$line[43..44]);
+			push(@row, (@$line[44] * 100) / @$line[43]);
+			$line1 .= "%8d %8d %3.1f ";
+			$line1 .= " ";
+			push(@row, @$line[32..34]);
+			$line1 .= "%4d %4d %4d ";
+			$line1 .= " ";
+			push(@row, @$line[37..40]);
+			$line1 .= "%4d %4d %4d %4d ";
+			$line1 .= " ";
+			push(@row, @$line[47..48]);
+			$line1 .= " %6d %6d ";
+			$line1 .= " ";
+			push(@row, @$line[50..51]);
+			$line1 .= " %6d %6d ";
+			$time = $time - (1 / $ts);
+			printf(" %2d$tc  $line1\n", $time, @row);
+		}
+		print("    
\n"); + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; + } + + if($title) { + graph_header($title, 2); + } + if($SQUID1_RIGID eq 1) { + push(@riglim, "--upper-limit=$SQUID1_LIMIT"); + } else { + if($SQUID1_RIGID eq 2) { + push(@riglim, "--upper-limit=$SQUID1_LIMIT"); + push(@riglim, "--rigid"); + } + } + if($title) { + print(" \n"); + print(" \n"); + } + for($n = 0, $i = 1; $n < 9; $n++, $i++) { + if($SQUID_GRAPH_1[$n]) { + $str = sprintf("%-34s", $SQUID_GRAPH_1[$n]); + $str = substr($str, 0, 23); + push(@DEF, "DEF:squid_g1_$i=$SQUID_RRD:squid_g1_$i:AVERAGE"); + push(@tmp, "LINE1:squid_g1_$i$AC[$n]:$str"); + push(@tmp, "GPRINT:squid_g1_$i:LAST:Cur\\: %6.1lf"); + push(@tmp, "GPRINT:squid_g1_$i:AVERAGE: Avg\\: %6.1lf"); + push(@tmp, "GPRINT:squid_g1_$i:MIN: Min\\: %6.1lf"); + push(@tmp, "GPRINT:squid_g1_$i:MAX: Max\\: %6.1lf\\n"); + push(@tmpz, "LINE2:squid_g1_$i$AC[$n]:$SQUID_GRAPH_1[$n]"); + } else { + push(@tmp, "COMMENT: \\n"); + } + } + ($width, $height) = split('x', $GRAPH_SIZE{main}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG1", + "--title=$rgraphs{_squid1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Values/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + @DEF, + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG1: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG1z", + "--title=$rgraphs{_squid1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Values/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + @DEF, + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG1z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /squid1/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@riglim); + if($SQUID2_RIGID eq 1) { + push(@riglim, "--upper-limit=$SQUID2_LIMIT"); + } else { + if($SQUID2_RIGID eq 2) { + push(@riglim, "--upper-limit=$SQUID2_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + undef(@DEF); + for($n = 0, $i = 1; $n < 9; $n++, $i++) { + if($SQUID_GRAPH_2[$n]) { + $str = sprintf("%-34s", $SQUID_GRAPH_2[$n]); + $str = substr($str, 0, 23); + push(@DEF, "DEF:squid_g2_$i=$SQUID_RRD:squid_g2_$i:AVERAGE"); + push(@tmp, "LINE1:squid_g2_$i$AC[$n]:$str"); + push(@tmp, "GPRINT:squid_g2_$i:LAST:Cur\\: %6.1lf"); + push(@tmp, "GPRINT:squid_g2_$i:AVERAGE: Avg\\: %6.1lf"); + push(@tmp, "GPRINT:squid_g2_$i:MIN: Min\\: %6.1lf"); + push(@tmp, "GPRINT:squid_g2_$i:MAX: Max\\: %6.1lf\\n"); + push(@tmpz, "LINE2:squid_g2_$i$AC[$n]:$SQUID_GRAPH_2[$n]"); + } else { + push(@tmp, "COMMENT: \\n"); + } + } + ($width, $height) = split('x', $GRAPH_SIZE{main}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG2", + "--title=$rgraphs{_squid2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Values/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + @DEF, + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG2: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG2z", + "--title=$rgraphs{_squid2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Values/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + @DEF, + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG2z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /squid2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@riglim); + if($SQUID3_RIGID eq 1) { + push(@riglim, "--upper-limit=$SQUID3_LIMIT"); + } else { + if($SQUID3_RIGID eq 2) { + push(@riglim, "--upper-limit=$SQUID3_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + undef(@DEF); + push(@tmp, "LINE1:squid_rq_1$AC[0]:Client HTTP requests"); + push(@tmp, "GPRINT:squid_rq_1:LAST: Cur\\: %6.1lf"); + push(@tmp, "GPRINT:squid_rq_1:AVERAGE: Avg\\: %6.1lf"); + push(@tmp, "GPRINT:squid_rq_1:MIN: Min\\: %6.1lf"); + push(@tmp, "GPRINT:squid_rq_1:MAX: Max\\: %6.1lf\\n"); + push(@tmp, "LINE1:squid_rq_2$AC[1]:Client HTTP hits"); + push(@tmp, "GPRINT:squid_rq_2:LAST: Cur\\: %6.1lf"); + push(@tmp, "GPRINT:squid_rq_2:AVERAGE: Avg\\: %6.1lf"); + push(@tmp, "GPRINT:squid_rq_2:MIN: Min\\: %6.1lf"); + push(@tmp, "GPRINT:squid_rq_2:MAX: Max\\: %6.1lf\\n"); + push(@tmp, "LINE1:squid_rq_3$AC[2]:Server HTTP requests"); + push(@tmp, "GPRINT:squid_rq_3:LAST: Cur\\: %6.1lf"); + push(@tmp, "GPRINT:squid_rq_3:AVERAGE: Avg\\: %6.1lf"); + push(@tmp, "GPRINT:squid_rq_3:MIN: Min\\: %6.1lf"); + push(@tmp, "GPRINT:squid_rq_3:MAX: Max\\: %6.1lf\\n"); + push(@tmp, "LINE1:squid_rq_4$AC[3]:Server FTP requests"); + push(@tmp, "GPRINT:squid_rq_4:LAST: Cur\\: %6.1lf"); + push(@tmp, "GPRINT:squid_rq_4:AVERAGE: Avg\\: %6.1lf"); + push(@tmp, "GPRINT:squid_rq_4:MIN: Min\\: %6.1lf"); + push(@tmp, "GPRINT:squid_rq_4:MAX: Max\\: %6.1lf\\n"); + push(@tmp, "LINE1:squid_rq_5$AC[4]:Server Other requests"); + push(@tmp, "GPRINT:squid_rq_5:LAST: Cur\\: %6.1lf"); + push(@tmp, "GPRINT:squid_rq_5:AVERAGE: Avg\\: %6.1lf"); + push(@tmp, "GPRINT:squid_rq_5:MIN: Min\\: %6.1lf"); + push(@tmp, "GPRINT:squid_rq_5:MAX: Max\\: %6.1lf\\n"); + push(@tmp, "LINE1:squid_rq_6$AC[5]:Aborted requests"); + push(@tmp, "GPRINT:squid_rq_6:LAST: Cur\\: %6.1lf"); + push(@tmp, "GPRINT:squid_rq_6:AVERAGE: Avg\\: %6.1lf"); + push(@tmp, "GPRINT:squid_rq_6:MIN: Min\\: %6.1lf"); + push(@tmp, "GPRINT:squid_rq_6:MAX: Max\\: %6.1lf\\n"); + push(@tmp, "LINE1:squid_rq_7$AC[6]:Swap files cleaned"); + push(@tmp, "GPRINT:squid_rq_7:LAST: Cur\\: %6.1lf"); + push(@tmp, "GPRINT:squid_rq_7:AVERAGE: Avg\\: %6.1lf"); + push(@tmp, "GPRINT:squid_rq_7:MIN: Min\\: %6.1lf"); + push(@tmp, "GPRINT:squid_rq_7:MAX: Max\\: %6.1lf\\n"); + push(@tmp, "LINE1:squid_rq_8$AC[7]:Unlink requests"); + push(@tmp, "GPRINT:squid_rq_8:LAST: Cur\\: %6.1lf"); + push(@tmp, "GPRINT:squid_rq_8:AVERAGE: Avg\\: %6.1lf"); + push(@tmp, "GPRINT:squid_rq_8:MIN: Min\\: %6.1lf"); + push(@tmp, "GPRINT:squid_rq_8:MAX: Max\\: %6.1lf\\n"); + push(@tmpz, "LINE2:squid_rq_1$AC[0]:Client HTTP requests"); + push(@tmpz, "LINE2:squid_rq_2$AC[1]:Client HTTP hits"); + push(@tmpz, "LINE2:squid_rq_3$AC[2]:Server HTTP requests"); + push(@tmpz, "LINE2:squid_rq_4$AC[3]:Server FTP requests"); + push(@tmpz, "LINE2:squid_rq_5$AC[4]:Server Other requests"); + push(@tmpz, "LINE2:squid_rq_6$AC[5]:Aborted requests"); + push(@tmpz, "LINE2:squid_rq_7$AC[6]:Swap files cleaned"); + push(@tmpz, "LINE2:squid_rq_8$AC[7]:Unlink requests"); + ($width, $height) = split('x', $GRAPH_SIZE{main}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG3", + "--title=$rgraphs{_squid3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Values/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:squid_rq_1=$SQUID_RRD:squid_rq_1:AVERAGE", + "DEF:squid_rq_2=$SQUID_RRD:squid_rq_2:AVERAGE", + "DEF:squid_rq_3=$SQUID_RRD:squid_rq_3:AVERAGE", + "DEF:squid_rq_4=$SQUID_RRD:squid_rq_4:AVERAGE", + "DEF:squid_rq_5=$SQUID_RRD:squid_rq_5:AVERAGE", + "DEF:squid_rq_6=$SQUID_RRD:squid_rq_6:AVERAGE", + "DEF:squid_rq_7=$SQUID_RRD:squid_rq_7:AVERAGE", + "DEF:squid_rq_8=$SQUID_RRD:squid_rq_8:AVERAGE", + "DEF:squid_rq_9=$SQUID_RRD:squid_rq_9:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG3: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG3z", + "--title=$rgraphs{_squid3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Values/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:squid_rq_1=$SQUID_RRD:squid_rq_1:AVERAGE", + "DEF:squid_rq_2=$SQUID_RRD:squid_rq_2:AVERAGE", + "DEF:squid_rq_3=$SQUID_RRD:squid_rq_3:AVERAGE", + "DEF:squid_rq_4=$SQUID_RRD:squid_rq_4:AVERAGE", + "DEF:squid_rq_5=$SQUID_RRD:squid_rq_5:AVERAGE", + "DEF:squid_rq_6=$SQUID_RRD:squid_rq_6:AVERAGE", + "DEF:squid_rq_7=$SQUID_RRD:squid_rq_7:AVERAGE", + "DEF:squid_rq_8=$SQUID_RRD:squid_rq_8:AVERAGE", + "DEF:squid_rq_9=$SQUID_RRD:squid_rq_9:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG3z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /squid3/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + if($title) { + print(" \n"); + print(" \n"); + } + + undef(@riglim); + if($SQUID4_RIGID eq 1) { + push(@riglim, "--upper-limit=$SQUID4_LIMIT"); + } else { + if($SQUID4_RIGID eq 2) { + push(@riglim, "--upper-limit=$SQUID4_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + push(@tmp, "LINE1:m_alloc#EEEE44:Allocated"); + push(@tmp, "GPRINT:m_alloc:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "AREA:m_inuse#44AAEE:In use"); + push(@tmp, "LINE1:m_inuse#00AAEE:"); + push(@tmp, "GPRINT:m_inuse:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "GPRINT:m_perc:LAST: In use\\: %5.1lf%%\\n"); + push(@tmpz, "LINE2:m_alloc#EEEE44:Allocated"); + push(@tmpz, "AREA:m_inuse#44AAEE:In use"); + push(@tmpz, "LINE2:m_inuse#00AAEE:"); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG4", + "--title=$rgraphs{_squid4} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Megabytes", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:squid_m_1=$SQUID_RRD:squid_m_1:AVERAGE", + "DEF:squid_m_2=$SQUID_RRD:squid_m_2:AVERAGE", + "CDEF:m_alloc=squid_m_1,1024,/", + "CDEF:m_inuse=squid_m_2,1024,/", + "CDEF:m_perc=squid_m_2,100,*,squid_m_1,/", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG4: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG4z", + "--title=$rgraphs{_squid4} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Megabytes", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:squid_m_1=$SQUID_RRD:squid_m_1:AVERAGE", + "DEF:squid_m_2=$SQUID_RRD:squid_m_2:AVERAGE", + "CDEF:m_alloc=squid_m_1,1024,/", + "CDEF:m_inuse=squid_m_2,1024,/", + "CDEF:m_perc=squid_m_2,100,*,squid_m_1,/", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG4z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /squid4/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@riglim); + if($SQUID5_RIGID eq 1) { + push(@riglim, "--upper-limit=$SQUID5_LIMIT"); + } else { + if($SQUID5_RIGID eq 2) { + push(@riglim, "--upper-limit=$SQUID5_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + push(@tmp, "LINE1:s_alloc#EEEE44:Allocated"); + push(@tmp, "GPRINT:s_alloc:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "AREA:s_inuse#44AAEE:In use"); + push(@tmp, "GPRINT:s_inuse:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "LINE1:s_inuse#00AAEE:"); + push(@tmp, "GPRINT:s_perc:LAST: In use\\: %5.1lf%%\\n"); + push(@tmpz, "LINE2:s_alloc#EEEE44:Allocated"); + push(@tmpz, "AREA:s_inuse#44AAEE:In use"); + push(@tmpz, "LINE2:s_inuse#00AAEE:"); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG5", + "--title=$rgraphs{_squid5} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Megabytes", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:squid_s_2=$SQUID_RRD:squid_s_2:AVERAGE", + "DEF:squid_s_3=$SQUID_RRD:squid_s_3:AVERAGE", + "CDEF:s_alloc=squid_s_2,1024,/", + "CDEF:s_inuse=squid_s_3,1024,/", + "CDEF:s_perc=squid_s_3,100,*,squid_s_2,/", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG5: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG5z", + "--title=$rgraphs{_squid5} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Megabytes", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:squid_s_2=$SQUID_RRD:squid_s_2:AVERAGE", + "DEF:squid_s_3=$SQUID_RRD:squid_s_3:AVERAGE", + "CDEF:s_alloc=squid_s_2,1024,/", + "CDEF:s_inuse=squid_s_3,1024,/", + "CDEF:s_perc=squid_s_3,100,*,squid_s_2,/", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG5z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /squid5/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@riglim); + if($SQUID6_RIGID eq 1) { + push(@riglim, "--upper-limit=$SQUID6_LIMIT"); + } else { + if($SQUID6_RIGID eq 2) { + push(@riglim, "--upper-limit=$SQUID6_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + push(@tmp, "AREA:ic_requests#44EEEE:Requests"); + push(@tmp, "GPRINT:ic_requests:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "AREA:ic_hits#4444EE:Hits"); + push(@tmp, "GPRINT:ic_hits:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "AREA:ic_misses#EE44EE:Misses"); + push(@tmp, "GPRINT:ic_misses:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "LINE1:ic_requests#00EEEE"); + push(@tmp, "LINE1:ic_hits#0000EE"); + push(@tmp, "LINE1:ic_misses#EE00EE"); + push(@tmpz, "AREA:ic_requests#44EEEE:Requests"); + push(@tmpz, "AREA:ic_hits#4444EE:Hits"); + push(@tmpz, "AREA:ic_misses#EE44EE:Misses"); + push(@tmpz, "LINE1:ic_requests#00EEEE"); + push(@tmpz, "LINE1:ic_hits#0000EE"); + push(@tmpz, "LINE1:ic_misses#EE00EE"); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG6", + "--title=$rgraphs{_squid6} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Values/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:ic_requests=$SQUID_RRD:squid_ic_1:AVERAGE", + "DEF:ic_hits=$SQUID_RRD:squid_ic_2:AVERAGE", + "DEF:ic_misses=$SQUID_RRD:squid_ic_3:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG6: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG6z", + "--title=$rgraphs{_squid6} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Values/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:ic_requests=$SQUID_RRD:squid_ic_1:AVERAGE", + "DEF:ic_hits=$SQUID_RRD:squid_ic_2:AVERAGE", + "DEF:ic_misses=$SQUID_RRD:squid_ic_3:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG6z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /squid6/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@riglim); + if($SQUID7_RIGID eq 1) { + push(@riglim, "--upper-limit=$SQUID7_LIMIT"); + } else { + if($SQUID7_RIGID eq 2) { + push(@riglim, "--upper-limit=$SQUID7_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + push(@tmp, "AREA:io_http#44EEEE:HTTP"); + push(@tmp, "GPRINT:io_http:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "AREA:io_ftp#4444EE:FTP"); + push(@tmp, "GPRINT:io_ftp:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "AREA:io_gopher#EE44EE:Gopher"); + push(@tmp, "GPRINT:io_gopher:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "AREA:io_wais#EEEE44:WAIS"); + push(@tmp, "GPRINT:io_wais:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "LINE1:io_http#00EEEE"); + push(@tmp, "LINE1:io_ftp#0000EE"); + push(@tmp, "LINE1:io_gopher#EE00EE"); + push(@tmp, "LINE1:io_wais#EEEE00"); + push(@tmpz, "AREA:io_http#44EEEE:HTTP"); + push(@tmpz, "AREA:io_ftp#4444EE:FTP"); + push(@tmpz, "AREA:io_gopher#EE44EE:Gopher"); + push(@tmpz, "AREA:io_wais#EEEE44:WAIS"); + push(@tmpz, "LINE1:io_http#44EEEE"); + push(@tmpz, "LINE1:io_ftp#4444EE"); + push(@tmpz, "LINE1:io_gopher#EE44EE"); + push(@tmpz, "LINE1:io_wais#EEEE44"); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG7", + "--title=$rgraphs{_squid7} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Reads/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:io_http=$SQUID_RRD:squid_io_1:AVERAGE", + "DEF:io_ftp=$SQUID_RRD:squid_io_2:AVERAGE", + "DEF:io_gopher=$SQUID_RRD:squid_io_3:AVERAGE", + "DEF:io_wais=$SQUID_RRD:squid_io_4:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG7: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG7z", + "--title=$rgraphs{_squid7} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Reads/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:io_http=$SQUID_RRD:squid_io_1:AVERAGE", + "DEF:io_ftp=$SQUID_RRD:squid_io_2:AVERAGE", + "DEF:io_gopher=$SQUID_RRD:squid_io_3:AVERAGE", + "DEF:io_wais=$SQUID_RRD:squid_io_4:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG7z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /squid7/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@riglim); + if($SQUID8_RIGID eq 1) { + push(@riglim, "--upper-limit=$SQUID8_LIMIT"); + } else { + if($SQUID8_RIGID eq 2) { + push(@riglim, "--upper-limit=$SQUID8_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + push(@tmp, "AREA:in#44EE44:Input"); + push(@tmp, "AREA:out#4444EE:Output"); + push(@tmp, "AREA:out#4444EE:"); + push(@tmp, "AREA:in#44EE44:"); + push(@tmp, "LINE1:out#0000EE"); + push(@tmp, "LINE1:in#00EE00"); + push(@tmpz, "AREA:in#44EE44:Input"); + push(@tmpz, "AREA:out#4444EE:Output"); + push(@tmpz, "AREA:out#4444EE:"); + push(@tmpz, "AREA:in#44EE44:"); + push(@tmpz, "LINE1:out#0000EE"); + push(@tmpz, "LINE1:in#00EE00"); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG8", + "--title=$rgraphs{_squid8} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=bytes/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:in=$SQUID_RRD:squid_tc_1:AVERAGE", + "DEF:out=$SQUID_RRD:squid_tc_2:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG8: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG8z", + "--title=$rgraphs{_squid8} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=bytes/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:in=$SQUID_RRD:squid_tc_1:AVERAGE", + "DEF:out=$SQUID_RRD:squid_tc_2:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG8z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /squid8/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@riglim); + if($SQUID9_RIGID eq 1) { + push(@riglim, "--upper-limit=$SQUID9_LIMIT"); + } else { + if($SQUID9_RIGID eq 2) { + push(@riglim, "--upper-limit=$SQUID9_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + push(@tmp, "AREA:in#44EE44:Input"); + push(@tmp, "AREA:out#4444EE:Output"); + push(@tmp, "AREA:out#4444EE:"); + push(@tmp, "AREA:in#44EE44:"); + push(@tmp, "LINE1:out#0000EE"); + push(@tmp, "LINE1:in#00EE00"); + push(@tmpz, "AREA:in#44EE44:Input"); + push(@tmpz, "AREA:out#4444EE:Output"); + push(@tmpz, "AREA:out#4444EE:"); + push(@tmpz, "AREA:in#44EE44:"); + push(@tmpz, "LINE1:out#0000EE"); + push(@tmpz, "LINE1:in#00EE00"); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG9", + "--title=$rgraphs{_squid9} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=bytes/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:in=$SQUID_RRD:squid_ts_1:AVERAGE", + "DEF:out=$SQUID_RRD:squid_ts_2:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG9: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG9z", + "--title=$rgraphs{_squid9} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=bytes/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:in=$SQUID_RRD:squid_ts_1:AVERAGE", + "DEF:out=$SQUID_RRD:squid_ts_2:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG9z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /squid9/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; +} + +# NFSS graph +# ---------------------------------------------------------------------------- +sub nfss { + my ($myself, $title) = @_; + + my $width; + my $height; + my @riglim; + my @tmp; + my @tmpz; + my $i; + my @DEF; + my $n; + my $err; + my @AC = ( + "#FFA500", + "#44EEEE", + "#44EE44", + "#4444EE", + "#448844", + "#EE4444", + "#EE44EE", + "#EEEE44", + "#963C74", + "#CCCCCC", + ); + my @LC = ( + "#FFA500", + "#00EEEE", + "#00EE00", + "#0000EE", + "#448844", + "#EE0000", + "#EE00EE", + "#EEEE00", + "#B4B444", + "#888888", + ); + + my $PNG1 = $u . $myself . "1." . $when . ".png"; + my $PNG2 = $u . $myself . "2." . $when . ".png"; + my $PNG3 = $u . $myself . "3." . $when . ".png"; + my $PNG4 = $u . $myself . "4." . $when . ".png"; + my $PNG5 = $u . $myself . "5." . $when . ".png"; + my $PNG6 = $u . $myself . "6." . $when . ".png"; + my $PNG7 = $u . $myself . "7." . $when . ".png"; + my $PNG8 = $u . $myself . "8." . $when . ".png"; + my $PNG9 = $u . $myself . "9." . $when . ".png"; + my $PNG1z = $u . $myself . "1z." . $when . ".png"; + my $PNG2z = $u . $myself . "2z." . $when . ".png"; + my $PNG3z = $u . $myself . "3z." . $when . ".png"; + my $PNG4z = $u . $myself . "4z." . $when . ".png"; + my $PNG5z = $u . $myself . "5z." . $when . ".png"; + my $PNG6z = $u . $myself . "6z." . $when . ".png"; + my $PNG7z = $u . $myself . "7z." . $when . ".png"; + my $PNG8z = $u . $myself . "8z." . $when . ".png"; + my $PNG9z = $u . $myself . "9z." . $when . ".png"; + + my @nfsv; + if($NFSS_VERSION eq "2") { + @nfsv = @nfsv2; + } elsif($NFSS_VERSION eq "4") { + @nfsv = @nfsv4; + } else { + @nfsv = @nfsv3; + } + + $title = !$silent ? $title : ""; + $title =~ s/NFS/NFS v$NFSS_VERSION/; + + unlink ("$PNG_DIR" . "$PNG1", + "$PNG_DIR" . "$PNG2", + "$PNG_DIR" . "$PNG3", + "$PNG_DIR" . "$PNG4", + "$PNG_DIR" . "$PNG5", + "$PNG_DIR" . "$PNG6", + "$PNG_DIR" . "$PNG7", + "$PNG_DIR" . "$PNG8", + "$PNG_DIR" . "$PNG9"); + if($ENABLE_ZOOM eq "Y") { + unlink ("$PNG_DIR" . "$PNG1z", + "$PNG_DIR" . "$PNG2z", + "$PNG_DIR" . "$PNG3z", + "$PNG_DIR" . "$PNG4z", + "$PNG_DIR" . "$PNG5z", + "$PNG_DIR" . "$PNG6z", + "$PNG_DIR" . "$PNG7z", + "$PNG_DIR" . "$PNG8z", + "$PNG_DIR" . "$PNG9z"); + } + + if($IFACE_MODE eq "text") { + if($title) { + graph_header($title, 2); + print(" \n"); + print(" \n"); + } + my (undef, undef, undef, $data) = RRDs::fetch("$NFSS_RRD", + "--start=-$nwhen$twhen", + "AVERAGE", + "-r $res"); + $err = RRDs::error; + print("ERROR: while fetching $NFSS_RRD: $err\n") if $err; + my $str; + my $line1; + my $line2; + print("
\n");
+		foreach my $t (@nfsv) {
+			$str = sprintf("%12s ", $t);
+			$line1 .= $str;
+			$line2 .= "-------------";
+		}
+		$line1 .= sprintf("%12s %12s %12s ", "hits", "misses", "nocache");
+		$line2 .= "-------------" . "-------------" . "-------------";
+		$line1 .= sprintf("%12s %12s %12s %12s %12s ", "lookup", "anon", "ncachedir", "ncachedir", "stale");
+		$line2 .= "-------------" . "-------------" . "-------------" . "-------------" . "-------------";
+		$line1 .= sprintf("%12s %12s ", "read", "written");
+		$line2 .= "-------------" . "-------------";
+		$line1 .= sprintf("%12s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s ", "threads", "<10%", "<20%", "<30%", "<40%", "<50%", "<60%", "<70%", "<80%", "<90%", "<100%");
+		$line2 .= "-------------" . "-------" . "-------" . "-------" . "-------" . "-------" . "-------" . "-------" . "-------" . "-------" . "-------";
+		$line1 .= sprintf("%12s %12s %12s %12s ", "packets", "udp", "tcp", "tcpconn");
+		$line2 .= "-------------" . "-------------" . "-------------" . "-------------";
+		$line1 .= sprintf("%12s %12s %12s %12s %12s ", "calls", "badcalls", "badauth", "badclnt", "xdrcall");
+		$line2 .= "-------------" . "-------------" . "-------------" . "-------------" . "-------------";
+		print("Time $line1\n");
+		print("-----$line2\n");
+		my $line;
+		my @row;
+		my $time;
+		my $n2;
+		my @nfs;
+		for($n = 0, $time = $tb; $n < ($tb * $ts); $n++) {
+			$line = @$data[$n];
+			undef($line1);
+			undef(@row);
+			(@nfs) = @$line[0..scalar(@nfsv) - 1];
+			for($n2 = 0; $n2 < scalar(@nfs);$n2++) {
+				push(@row, $nfs[$n2]);
+				$line1 .= "%12d ";
+			}
+			push(@row, @$line[50..52]);
+			$line1 .= "%12d %12d %12d ";
+			push(@row, @$line[55..59]);
+			$line1 .= "%12d %12d %12d %12d %12d ";
+			push(@row, @$line[60..61]);
+			$line1 .= "%12d %12d ";
+			push(@row, @$line[63..73]);
+			$line1 .= "%12d %6d %6d %6d %6d %6d %6d %6d %6d %6d %6d ";
+			push(@row, @$line[74..77]);
+			$line1 .= "%12d %12d %12d %12d ";
+			push(@row, @$line[79..83]);
+			$line1 .= "%12d %12d %12d %12d %12d ";
+			$time = $time - (1 / $ts);
+			printf(" %2d$tc $line1\n", $time, @row);
+		}
+		print("    
\n"); + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; + } + + if($title) { + graph_header($title, 2); + } + if($NFSS1_RIGID eq 1) { + push(@riglim, "--upper-limit=$NFSS1_LIMIT"); + } else { + if($NFSS1_RIGID eq 2) { + push(@riglim, "--upper-limit=$NFSS1_LIMIT"); + push(@riglim, "--rigid"); + } + } + if($title) { + print(" \n"); + print(" \n"); + } + for($n = 0; $n < 10; $n++) { + if(grep {$_ eq $NFSS_GRAPH_1[$n]} @nfsv) { + ($i) = grep { $nfsv[$_] eq $NFSS_GRAPH_1[$n] } 0..$#nfsv; + push(@DEF, "DEF:nfs_$i=$NFSS_RRD:nfss_$i:AVERAGE"); + push(@tmp, "LINE1:nfs_$i$AC[$n]:" . sprintf("%-12s", $NFSS_GRAPH_1[$n])); + push(@tmp, "GPRINT:nfs_$i:LAST: Cur\\: %6.1lf"); + push(@tmp, "GPRINT:nfs_$i:AVERAGE: Avg\\: %6.1lf"); + push(@tmp, "GPRINT:nfs_$i:MIN: Min\\: %6.1lf"); + push(@tmp, "GPRINT:nfs_$i:MAX: Max\\: %6.1lf\\n"); + push(@tmpz, "LINE2:nfs_$i$AC[$n]:" . sprintf("%-12s", $NFSS_GRAPH_1[$n])); + } else { + push(@tmp, "COMMENT: \\n"); + } + } + ($width, $height) = split('x', $GRAPH_SIZE{main}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG1", + "--title=$rgraphs{_nfss1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Requests/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + @DEF, + @tmp, + "COMMENT: \\n"); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG1: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG1z", + "--title=$rgraphs{_nfss1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Requests/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + @DEF, + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG1z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /nfss1/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@riglim); + if($NFSS2_RIGID eq 1) { + push(@riglim, "--upper-limit=$NFSS2_LIMIT"); + } else { + if($NFSS2_RIGID eq 2) { + push(@riglim, "--upper-limit=$NFSS2_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + undef(@DEF); + for($n = 0; $n < 10; $n++) { + if(grep {$_ eq $NFSS_GRAPH_2[$n]} @nfsv) { + ($i) = grep { $nfsv[$_] eq $NFSS_GRAPH_2[$n] } 0..$#nfsv; + push(@DEF, "DEF:nfs_$i=$NFSS_RRD:nfss_$i:AVERAGE"); + push(@tmp, "LINE1:nfs_$i$AC[$n]:" . sprintf("%-12s", $NFSS_GRAPH_2[$n])); + push(@tmp, "GPRINT:nfs_$i:LAST: Cur\\: %6.1lf"); + push(@tmp, "GPRINT:nfs_$i:AVERAGE: Avg\\: %6.1lf"); + push(@tmp, "GPRINT:nfs_$i:MIN: Min\\: %6.1lf"); + push(@tmp, "GPRINT:nfs_$i:MAX: Max\\: %6.1lf\\n"); + push(@tmpz, "LINE2:nfs_$i$AC[$n]:" . sprintf("%-12s", $NFSS_GRAPH_2[$n])); + } else { + push(@tmp, "COMMENT: \\n"); + } + } + ($width, $height) = split('x', $GRAPH_SIZE{main}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG2", + "--title=$rgraphs{_nfss2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Requests/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + @DEF, + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG2: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG2z", + "--title=$rgraphs{_nfss2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Requests/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + @DEF, + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG2z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /nfss2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@riglim); + if($NFSS3_RIGID eq 1) { + push(@riglim, "--upper-limit=$NFSS3_LIMIT"); + } else { + if($NFSS3_RIGID eq 2) { + push(@riglim, "--upper-limit=$NFSS3_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + undef(@DEF); + for($n = 0; $n < 10; $n++) { + if(grep {$_ eq $NFSS_GRAPH_3[$n]} @nfsv) { + ($i) = grep { $nfsv[$_] eq $NFSS_GRAPH_3[$n] } 0..$#nfsv; + push(@DEF, "DEF:nfs_$i=$NFSS_RRD:nfss_$i:AVERAGE"); + push(@tmp, "LINE1:nfs_$i$AC[$n]:" . sprintf("%-12s", $NFSS_GRAPH_3[$n])); + push(@tmp, "GPRINT:nfs_$i:LAST: Cur\\: %6.1lf"); + push(@tmp, "GPRINT:nfs_$i:AVERAGE: Avg\\: %6.1lf"); + push(@tmp, "GPRINT:nfs_$i:MIN: Min\\: %6.1lf"); + push(@tmp, "GPRINT:nfs_$i:MAX: Max\\: %6.1lf\\n"); + push(@tmpz, "LINE2:nfs_$i$AC[$n]:" . sprintf("%-12s", $NFSS_GRAPH_3[$n])); + } else { + push(@tmp, "COMMENT: \\n"); + } + } + ($width, $height) = split('x', $GRAPH_SIZE{main}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG3", + "--title=$rgraphs{_nfss3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Requests/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + @DEF, + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG3: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG3z", + "--title=$rgraphs{_nfss3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Requests/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + @DEF, + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG3z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /nfss3/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + if($title) { + print(" \n"); + print(" \n"); + } + + undef(@riglim); + if($NFSS4_RIGID eq 1) { + push(@riglim, "--upper-limit=$NFSS4_LIMIT"); + } else { + if($NFSS4_RIGID eq 2) { + push(@riglim, "--upper-limit=$NFSS4_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + push(@tmp, "AREA:in#44EE44:Read"); + push(@tmp, "AREA:out#4444EE:Written"); + push(@tmp, "AREA:out#4444EE:"); + push(@tmp, "AREA:in#44EE44:"); + push(@tmp, "LINE1:out#0000EE"); + push(@tmp, "LINE1:in#00EE00"); + push(@tmpz, "AREA:in#44EE44:Read"); + push(@tmpz, "AREA:out#4444EE:Written"); + push(@tmpz, "AREA:out#4444EE:"); + push(@tmpz, "AREA:in#44EE44:"); + push(@tmpz, "LINE1:out#0000EE"); + push(@tmpz, "LINE1:in#00EE00"); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG4", + "--title=$rgraphs{_nfss4} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=bytes/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:in=$NFSS_RRD:nfss_io_1:AVERAGE", + "DEF:out=$NFSS_RRD:nfss_io_2:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG4: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG4z", + "--title=$rgraphs{_nfss4} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=bytes/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:in=$NFSS_RRD:nfss_io_1:AVERAGE", + "DEF:out=$NFSS_RRD:nfss_io_2:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG4z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /nfss4/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@riglim); + if($NFSS5_RIGID eq 1) { + push(@riglim, "--upper-limit=$NFSS5_LIMIT"); + } else { + if($NFSS5_RIGID eq 2) { + push(@riglim, "--upper-limit=$NFSS5_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + push(@tmp, "AREA:udp#44EEEE:UDP"); + push(@tmp, "GPRINT:udp:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "AREA:tcp#4444EE:TCP"); + push(@tmp, "GPRINT:tcp:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "AREA:tcpconn#EE44EE:TCP Connections"); + push(@tmp, "GPRINT:tcpconn:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "LINE1:udp#00EEEE"); + push(@tmp, "LINE1:tcp#0000EE"); + push(@tmp, "LINE1:tcpconn#EE00EE"); + push(@tmpz, "AREA:udp#44EEEE:UDP"); + push(@tmpz, "AREA:tcp#4444EE:TCP"); + push(@tmpz, "AREA:tcpconn#EE44EE:TCP Connections"); + push(@tmpz, "LINE1:udp#00EEEE"); + push(@tmpz, "LINE1:tcp#0000EE"); + push(@tmpz, "LINE1:tcpconn#EE00EE"); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG5", + "--title=$rgraphs{_nfss5} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Values/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:packets=$NFSS_RRD:nfss_net_1:AVERAGE", + "DEF:udp=$NFSS_RRD:nfss_net_2:AVERAGE", + "DEF:tcp=$NFSS_RRD:nfss_net_3:AVERAGE", + "DEF:tcpconn=$NFSS_RRD:nfss_net_4:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG5: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG5z", + "--title=$rgraphs{_nfss5} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Values/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:packets=$NFSS_RRD:nfss_net_1:AVERAGE", + "DEF:udp=$NFSS_RRD:nfss_net_2:AVERAGE", + "DEF:tcp=$NFSS_RRD:nfss_net_3:AVERAGE", + "DEF:tcpconn=$NFSS_RRD:nfss_net_4:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG5z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /nfss5/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@riglim); + if($NFSS6_RIGID eq 1) { + push(@riglim, "--upper-limit=$NFSS6_LIMIT"); + } else { + if($NFSS6_RIGID eq 2) { + push(@riglim, "--upper-limit=$NFSS6_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + push(@tmp, "LINE1:calls#FFA500:Calls"); + push(@tmp, "GPRINT:calls:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "LINE1:badcalls#44EEEE:Badcalls"); + push(@tmp, "GPRINT:badcalls:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "LINE1:badauth#44EE44:Badauth"); + push(@tmp, "GPRINT:badauth:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "LINE1:badclnt#EE4444:Badclnt"); + push(@tmp, "GPRINT:badclnt:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "LINE1:xdrcall#4444EE:XDRcall"); + push(@tmp, "GPRINT:xdrcall:LAST: Current\\: %7.1lf\\n"); + push(@tmpz, "LINE1:calls#FFA500:Calls"); + push(@tmpz, "LINE1:badcalls#44EEEE:Badcalls"); + push(@tmpz, "LINE1:badauth#44EE44:Badauth"); + push(@tmpz, "LINE1:badclnt#EE4444:Badclnt"); + push(@tmpz, "LINE1:xdrcall#4444EE:XDRcall"); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG6", + "--title=$rgraphs{_nfss6} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Values/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:calls=$NFSS_RRD:nfss_rpc_1:AVERAGE", + "DEF:badcalls=$NFSS_RRD:nfss_rpc_2:AVERAGE", + "DEF:badauth=$NFSS_RRD:nfss_rpc_3:AVERAGE", + "DEF:badclnt=$NFSS_RRD:nfss_rpc_4:AVERAGE", + "DEF:xdrcall=$NFSS_RRD:nfss_rpc_4:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG6: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG6z", + "--title=$rgraphs{_nfss6} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Values/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:calls=$NFSS_RRD:nfss_rpc_1:AVERAGE", + "DEF:badcalls=$NFSS_RRD:nfss_rpc_2:AVERAGE", + "DEF:badauth=$NFSS_RRD:nfss_rpc_3:AVERAGE", + "DEF:badclnt=$NFSS_RRD:nfss_rpc_4:AVERAGE", + "DEF:xdrcall=$NFSS_RRD:nfss_rpc_4:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG6z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /nfss6/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@riglim); + if($NFSS7_RIGID eq 1) { + push(@riglim, "--upper-limit=$NFSS7_LIMIT"); + } else { + if($NFSS7_RIGID eq 2) { + push(@riglim, "--upper-limit=$NFSS7_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); +# push(@tmp, "LINE1:threads#444444:Threads usage"); +# push(@tmp, "GPRINT:threads:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "LINE1:th1#33FF00:<10%\\g"); + push(@tmp, "GPRINT:th1:LAST:\\: %7.1lf "); + push(@tmp, "LINE1:th2#FFCC00:< 60%\\g"); + push(@tmp, "GPRINT:th2:LAST:\\: %7.1lf\\n"); + push(@tmp, "LINE1:th3#66FF00:<20%\\g"); + push(@tmp, "GPRINT:th3:LAST:\\: %7.1lf "); + push(@tmp, "LINE1:th4#FF9900:< 70%\\g"); + push(@tmp, "GPRINT:th4:LAST:\\: %7.1lf\\n"); + push(@tmp, "LINE1:th5#99FF00:<30%\\g"); + push(@tmp, "GPRINT:th5:LAST:\\: %7.1lf "); + push(@tmp, "LINE1:th6#FF6600:< 80%\\g"); + push(@tmp, "GPRINT:th6:LAST:\\: %7.1lf\\n"); + push(@tmp, "LINE1:th7#CCFF00:<40%\\g"); + push(@tmp, "GPRINT:th7:LAST:\\: %7.1lf "); + push(@tmp, "LINE1:th8#FF3300:< 90%\\g"); + push(@tmp, "GPRINT:th8:LAST:\\: %7.1lf\\n"); + push(@tmp, "LINE1:th9#FFFF00:<50%\\g"); + push(@tmp, "GPRINT:th9:LAST:\\: %7.1lf "); + push(@tmp, "LINE1:th10#FF0000:<100%\\g"); + push(@tmp, "GPRINT:th10:LAST:\\: %7.1lf\\n"); +# push(@tmpz, "LINE1:threads#444444:Threads usage"); + push(@tmpz, "LINE1:th1#33FF00:<10%"); + push(@tmpz, "LINE1:th3#66FF00:<20%"); + push(@tmpz, "LINE1:th5#99FF00:<30%"); + push(@tmpz, "LINE1:th7#CCFF00:<40%"); + push(@tmpz, "LINE1:th9#FFFF00:<50%"); + push(@tmpz, "LINE1:th2#FFCC00:<60%"); + push(@tmpz, "LINE1:th4#FF9900:<70%"); + push(@tmpz, "LINE1:th6#FF6600:<80%"); + push(@tmpz, "LINE1:th8#FF3300:<90%"); + push(@tmpz, "LINE1:th10#FF0000:<100%"); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG7", + "--title=$rgraphs{_nfss7} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Values/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:threads=$NFSS_RRD:nfss_th_0:AVERAGE", + "DEF:th1=$NFSS_RRD:nfss_th_1:AVERAGE", + "DEF:th2=$NFSS_RRD:nfss_th_2:AVERAGE", + "DEF:th3=$NFSS_RRD:nfss_th_3:AVERAGE", + "DEF:th4=$NFSS_RRD:nfss_th_4:AVERAGE", + "DEF:th5=$NFSS_RRD:nfss_th_5:AVERAGE", + "DEF:th6=$NFSS_RRD:nfss_th_6:AVERAGE", + "DEF:th7=$NFSS_RRD:nfss_th_7:AVERAGE", + "DEF:th8=$NFSS_RRD:nfss_th_8:AVERAGE", + "DEF:th9=$NFSS_RRD:nfss_th_9:AVERAGE", + "DEF:th10=$NFSS_RRD:nfss_th_10:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG7: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG7z", + "--title=$rgraphs{_nfss7} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Values/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:threads=$NFSS_RRD:nfss_th_0:AVERAGE", + "DEF:th1=$NFSS_RRD:nfss_th_1:AVERAGE", + "DEF:th2=$NFSS_RRD:nfss_th_2:AVERAGE", + "DEF:th3=$NFSS_RRD:nfss_th_3:AVERAGE", + "DEF:th4=$NFSS_RRD:nfss_th_4:AVERAGE", + "DEF:th5=$NFSS_RRD:nfss_th_5:AVERAGE", + "DEF:th6=$NFSS_RRD:nfss_th_6:AVERAGE", + "DEF:th7=$NFSS_RRD:nfss_th_7:AVERAGE", + "DEF:th8=$NFSS_RRD:nfss_th_8:AVERAGE", + "DEF:th9=$NFSS_RRD:nfss_th_9:AVERAGE", + "DEF:th10=$NFSS_RRD:nfss_th_10:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG7z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /nfss7/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@riglim); + if($NFSS8_RIGID eq 1) { + push(@riglim, "--upper-limit=$NFSS8_LIMIT"); + } else { + if($NFSS8_RIGID eq 2) { + push(@riglim, "--upper-limit=$NFSS8_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + push(@tmp, "AREA:hits#44EEEE:Hits"); + push(@tmp, "GPRINT:hits:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "AREA:misses#4444EE:Misses"); + push(@tmp, "GPRINT:misses:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "AREA:nocache#EEEE44:Nocache"); + push(@tmp, "GPRINT:nocache:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "LINE1:hits#00EEEE"); + push(@tmp, "LINE1:misses#0000EE"); + push(@tmp, "LINE1:nocache#EEEE44"); + push(@tmpz, "AREA:hits#44EEEE:Hits"); + push(@tmpz, "AREA:misses#4444EE:Misses"); + push(@tmpz, "AREA:nocache#EEEE44:Nocache"); + push(@tmpz, "LINE1:hits#00EEEE"); + push(@tmpz, "LINE1:misses#0000EE"); + push(@tmpz, "LINE1:nocache#EEEE44"); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG8", + "--title=$rgraphs{_nfss8} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Requests/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:hits=$NFSS_RRD:nfss_rc_1:AVERAGE", + "DEF:misses=$NFSS_RRD:nfss_rc_2:AVERAGE", + "DEF:nocache=$NFSS_RRD:nfss_rc_3:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG8: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG8z", + "--title=$rgraphs{_nfss8} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Requests/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:hits=$NFSS_RRD:nfss_rc_1:AVERAGE", + "DEF:misses=$NFSS_RRD:nfss_rc_2:AVERAGE", + "DEF:nocache=$NFSS_RRD:nfss_rc_3:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG8z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /nfss8/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@riglim); + if($NFSS9_RIGID eq 1) { + push(@riglim, "--upper-limit=$NFSS9_LIMIT"); + } else { + if($NFSS9_RIGID eq 2) { + push(@riglim, "--upper-limit=$NFSS9_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + push(@tmp, "LINE1:lookup#FFA500:Lookups"); + push(@tmp, "GPRINT:lookup:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "LINE1:anon#44EE44:Anonymous lockups"); + push(@tmp, "GPRINT:anon:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "LINE1:ncachedir1#44EEEE:Ncachedir"); + push(@tmp, "GPRINT:ncachedir1:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "LINE1:ncachedir2#4444EE:Ncachedir"); + push(@tmp, "GPRINT:ncachedir2:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "LINE1:stale#EE4444:Stale"); + push(@tmp, "GPRINT:stale:LAST: Current\\: %7.1lf\\n"); + push(@tmpz, "LINE1:lookup#FFA500:Lookup"); + push(@tmpz, "LINE1:anon#44EE44:Anonymous"); + push(@tmpz, "LINE1:ncachedir1#44EEEE:Ncachedir"); + push(@tmpz, "LINE1:ncachedir2#4444EE:Ncachedir"); + push(@tmpz, "LINE1:stale#EE4444:Stale"); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG9", + "--title=$rgraphs{_nfss9} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Values/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:lookup=$NFSS_RRD:nfss_fh_1:AVERAGE", + "DEF:anon=$NFSS_RRD:nfss_fh_2:AVERAGE", + "DEF:ncachedir1=$NFSS_RRD:nfss_fh_3:AVERAGE", + "DEF:ncachedir2=$NFSS_RRD:nfss_fh_4:AVERAGE", + "DEF:stale=$NFSS_RRD:nfss_fh_4:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG9: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG9z", + "--title=$rgraphs{_nfss9} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Values/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:lookup=$NFSS_RRD:nfss_fh_1:AVERAGE", + "DEF:anon=$NFSS_RRD:nfss_fh_2:AVERAGE", + "DEF:ncachedir1=$NFSS_RRD:nfss_fh_3:AVERAGE", + "DEF:ncachedir2=$NFSS_RRD:nfss_fh_4:AVERAGE", + "DEF:stale=$NFSS_RRD:nfss_fh_4:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG9z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /nfss9/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; +} + +# NFSC graph +# ---------------------------------------------------------------------------- +sub nfsc { + my ($myself, $title) = @_; + + my $width; + my $height; + my @riglim; + my @tmp; + my @tmpz; + my @tmp1; + my @tmp2; + my @tmp1z; + my @tmp2z; + my $i; + my @DEF; + my $n; + my $err; + my @AC = ( + "#FFA500", + "#44EEEE", + "#44EE44", + "#4444EE", + "#448844", + "#EE4444", + "#EE44EE", + "#EEEE44", + "#963C74", + "#CCCCCC", + ); + my @LC = ( + "#FFA500", + "#00EEEE", + "#00EE00", + "#0000EE", + "#448844", + "#EE0000", + "#EE00EE", + "#EEEE00", + "#B4B444", + "#888888", + ); + + my $PNG1 = $u . $myself . "1." . $when . ".png"; + my $PNG2 = $u . $myself . "2." . $when . ".png"; + my $PNG3 = $u . $myself . "3." . $when . ".png"; + my $PNG4 = $u . $myself . "4." . $when . ".png"; + my $PNG5 = $u . $myself . "5." . $when . ".png"; + my $PNG6 = $u . $myself . "6." . $when . ".png"; + my $PNG1z = $u . $myself . "1z." . $when . ".png"; + my $PNG2z = $u . $myself . "2z." . $when . ".png"; + my $PNG3z = $u . $myself . "3z." . $when . ".png"; + my $PNG4z = $u . $myself . "4z." . $when . ".png"; + my $PNG5z = $u . $myself . "5z." . $when . ".png"; + my $PNG6z = $u . $myself . "6z." . $when . ".png"; + + my @nfsv; + if($NFSC_VERSION eq "2") { + @nfsv = @nfsv2; + } elsif($NFSC_VERSION eq "4") { + @nfsv = @nfsv4; + } else { + @nfsv = @nfsv3; + } + + $title = !$silent ? $title : ""; + $title =~ s/NFS/NFS v$NFSS_VERSION/; + + unlink ("$PNG_DIR" . "$PNG1", + "$PNG_DIR" . "$PNG2", + "$PNG_DIR" . "$PNG3", + "$PNG_DIR" . "$PNG4", + "$PNG_DIR" . "$PNG5", + "$PNG_DIR" . "$PNG6"); + if($ENABLE_ZOOM eq "Y") { + unlink ("$PNG_DIR" . "$PNG1z", + "$PNG_DIR" . "$PNG2z", + "$PNG_DIR" . "$PNG3z", + "$PNG_DIR" . "$PNG4z", + "$PNG_DIR" . "$PNG5z", + "$PNG_DIR" . "$PNG6z"); + } + + if($IFACE_MODE eq "text") { + if($title) { + graph_header($title, 2); + print(" \n"); + print(" \n"); + } + my (undef, undef, undef, $data) = RRDs::fetch("$NFSC_RRD", + "--start=-$nwhen$twhen", + "AVERAGE", + "-r $res"); + $err = RRDs::error; + print("ERROR: while fetching $NFSC_RRD: $err\n") if $err; + my $str; + my $line1; + my $line2; + print("
\n");
+		foreach my $t (@nfsv) {
+			$str = sprintf("%12s ", $t);
+			$line1 .= $str;
+			$line2 .= "-------------";
+		}
+		$line1 .= sprintf("%12s %12s %12s", "calls", "retrans", "authrefrsh");
+		$line2 .= "-------------" . "-------------" . "-------------";
+		print("Time $line1\n");
+		print("-----$line2\n");
+		my $line;
+		my @row;
+		my $time;
+		my $n2;
+		my @nfs;
+		for($n = 0, $time = $tb; $n < ($tb * $ts); $n++) {
+			$line = @$data[$n];
+			undef($line1);
+			undef(@row);
+			(@nfs) = @$line[0..scalar(@nfsv) - 1];
+			for($n2 = 0; $n2 < scalar(@nfs);$n2++) {
+				push(@row, $nfs[$n2]);
+				$line1 .= "%12d ";
+			}
+			push(@row, @$line[50..52]);
+			$line1 .= "%12d %12d %12d ";
+			$time = $time - (1 / $ts);
+			printf(" %2d$tc $line1\n", $time, @row);
+		}
+		print("    
\n"); + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; + } + + if($title) { + graph_header($title, 2); + } + if($NFSC1_RIGID eq 1) { + push(@riglim, "--upper-limit=$NFSC1_LIMIT"); + } else { + if($NFSC1_RIGID eq 2) { + push(@riglim, "--upper-limit=$NFSC1_LIMIT"); + push(@riglim, "--rigid"); + } + } + if($title) { + print(" \n"); + print(" \n"); + } + for($n = 0; $n < 10; $n++) { + if(grep {$_ eq $NFSC_GRAPH_1[$n]} @nfsv) { + ($i) = grep { $nfsv[$_] eq $NFSC_GRAPH_1[$n] } 0..$#nfsv; + push(@DEF, "DEF:nfs_$i=$NFSC_RRD:nfsc_$i:AVERAGE"); + push(@tmp, "LINE1:nfs_$i$AC[$n]:" . sprintf("%-12s", $NFSC_GRAPH_1[$n])); + push(@tmp, "GPRINT:nfs_$i:LAST: Cur\\: %6.1lf"); + push(@tmp, "GPRINT:nfs_$i:AVERAGE: Avg\\: %6.1lf"); + push(@tmp, "GPRINT:nfs_$i:MIN: Min\\: %6.1lf"); + push(@tmp, "GPRINT:nfs_$i:MAX: Max\\: %6.1lf\\n"); + push(@tmpz, "LINE2:nfs_$i$AC[$n]:" . sprintf("%-12s", $NFSC_GRAPH_1[$n])); + } else { + push(@tmp, "COMMENT: \\n"); + } + } + ($width, $height) = split('x', $GRAPH_SIZE{main}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG1", + "--title=$rgraphs{_nfsc1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Requests/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + @DEF, + @tmp, + "COMMENT: \\n"); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG1: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG1z", + "--title=$rgraphs{_nfsc1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Requests/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + @DEF, + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG1z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /nfsc1/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@riglim); + if($NFSC2_RIGID eq 1) { + push(@riglim, "--upper-limit=$NFSC2_LIMIT"); + } else { + if($NFSC2_RIGID eq 2) { + push(@riglim, "--upper-limit=$NFSC2_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + undef(@DEF); + for($n = 0; $n < 10; $n++) { + if(grep {$_ eq $NFSC_GRAPH_2[$n]} @nfsv) { + ($i) = grep { $nfsv[$_] eq $NFSC_GRAPH_2[$n] } 0..$#nfsv; + push(@DEF, "DEF:nfs_$i=$NFSC_RRD:nfsc_$i:AVERAGE"); + push(@tmp, "LINE1:nfs_$i$AC[$n]:" . sprintf("%-12s", $NFSC_GRAPH_2[$n])); + push(@tmp, "GPRINT:nfs_$i:LAST: Cur\\: %6.1lf"); + push(@tmp, "GPRINT:nfs_$i:AVERAGE: Avg\\: %6.1lf"); + push(@tmp, "GPRINT:nfs_$i:MIN: Min\\: %6.1lf"); + push(@tmp, "GPRINT:nfs_$i:MAX: Max\\: %6.1lf\\n"); + push(@tmpz, "LINE2:nfs_$i$AC[$n]:" . sprintf("%-12s", $NFSC_GRAPH_2[$n])); + } else { + push(@tmp, "COMMENT: \\n"); + } + } + ($width, $height) = split('x', $GRAPH_SIZE{main}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG2", + "--title=$rgraphs{_nfsc2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Requests/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + @DEF, + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG2: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG2z", + "--title=$rgraphs{_nfsc2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Requests/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + @DEF, + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG2z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /nfsc2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + if($title) { + print(" \n"); + print(" \n"); + } + + undef(@riglim); + if($NFSC3_RIGID eq 1) { + push(@riglim, "--upper-limit=$NFSC3_LIMIT"); + } else { + if($NFSC3_RIGID eq 2) { + push(@riglim, "--upper-limit=$NFSC3_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + undef(@tmp1); + undef(@tmp2); + undef(@tmp1z); + undef(@tmp2z); + undef(@DEF); + for($n = 0; $n < 4; $n++) { + if(grep {$_ eq $NFSC_GRAPH_3[$n]} @nfsv) { + ($i) = grep { $nfsv[$_] eq $NFSC_GRAPH_3[$n] } 0..$#nfsv; + push(@DEF, "DEF:nfs_$i=$NFSC_RRD:nfsc_$i:AVERAGE"); + push(@tmp1, "AREA:nfs_$i$AC[$n]:" . sprintf("%-12s", $NFSC_GRAPH_3[$n])); + push(@tmp1, "GPRINT:nfs_$i:LAST: Current\\: %6.1lf\\n"); + push(@tmp2, "LINE1:nfs_$i$LC[$n]"); + push(@tmp1z, "AREA:nfs_$i$AC[$n]:" . sprintf("%-12s", $NFSC_GRAPH_3[$n])); + push(@tmp2z, "LINE1:nfs_$i$LC[$n]"); + } else { + push(@tmp1, "COMMENT: \\n"); + } + } + @tmp = (@tmp1, @tmp2); + @tmpz = (@tmp1z, @tmp2z); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG3", + "--title=$rgraphs{_nfsc3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Requests/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + @DEF, + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG3: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG3z", + "--title=$rgraphs{_nfsc3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Requests/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + @DEF, + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG3z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /nfsc3/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@riglim); + if($NFSC4_RIGID eq 1) { + push(@riglim, "--upper-limit=$NFSC4_LIMIT"); + } else { + if($NFSC4_RIGID eq 2) { + push(@riglim, "--upper-limit=$NFSC4_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + undef(@tmp1); + undef(@tmp2); + undef(@tmp1z); + undef(@tmp2z); + undef(@DEF); + for($n = 0; $n < 4; $n++) { + if(grep {$_ eq $NFSC_GRAPH_4[$n]} @nfsv) { + ($i) = grep { $nfsv[$_] eq $NFSC_GRAPH_4[$n] } 0..$#nfsv; + push(@DEF, "DEF:nfs_$i=$NFSC_RRD:nfsc_$i:AVERAGE"); + push(@tmp1, "AREA:nfs_$i$AC[$n]:" . sprintf("%-12s", $NFSC_GRAPH_4[$n])); + push(@tmp1, "GPRINT:nfs_$i:LAST: Current\\: %6.1lf\\n"); + push(@tmp2, "LINE1:nfs_$i$LC[$n]"); + push(@tmp1z, "AREA:nfs_$i$AC[$n]:" . sprintf("%-12s", $NFSC_GRAPH_4[$n])); + push(@tmp2z, "LINE1:nfs_$i$LC[$n]"); + } else { + push(@tmp1, "COMMENT: \\n"); + } + } + @tmp = (@tmp1, @tmp2); + @tmpz = (@tmp1z, @tmp2z); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG4", + "--title=$rgraphs{_nfsc4} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Requests/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + @DEF, + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG4: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG4z", + "--title=$rgraphs{_nfsc4} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Requests/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + @DEF, + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG4z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /nfsc4/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@riglim); + if($NFSC5_RIGID eq 1) { + push(@riglim, "--upper-limit=$NFSC5_LIMIT"); + } else { + if($NFSC5_RIGID eq 2) { + push(@riglim, "--upper-limit=$NFSC5_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + undef(@tmp1); + undef(@tmp2); + undef(@tmp1z); + undef(@tmp2z); + undef(@DEF); + for($n = 0; $n < 4; $n++) { + if(grep {$_ eq $NFSC_GRAPH_5[$n]} @nfsv) { + ($i) = grep { $nfsv[$_] eq $NFSC_GRAPH_5[$n] } 0..$#nfsv; + push(@DEF, "DEF:nfs_$i=$NFSC_RRD:nfsc_$i:AVERAGE"); + push(@tmp1, "AREA:nfs_$i$AC[$n]:" . sprintf("%-12s", $NFSC_GRAPH_5[$n])); + push(@tmp1, "GPRINT:nfs_$i:LAST: Current\\: %6.1lf\\n"); + push(@tmp2, "LINE1:nfs_$i$LC[$n]"); + push(@tmp1z, "AREA:nfs_$i$AC[$n]:" . sprintf("%-12s", $NFSC_GRAPH_5[$n])); + push(@tmp2z, "LINE1:nfs_$i$LC[$n]"); + } else { + push(@tmp1, "COMMENT: \\n"); + } + } + @tmp = (@tmp1, @tmp2); + @tmpz = (@tmp1z, @tmp2z); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG5", + "--title=$rgraphs{_nfsc5} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Requests/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + @DEF, + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG5: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG5z", + "--title=$rgraphs{_nfsc5} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Requests/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + @DEF, + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG5z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /nfsc5/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@riglim); + if($NFSC6_RIGID eq 1) { + push(@riglim, "--upper-limit=$NFSC6_LIMIT"); + } else { + if($NFSC6_RIGID eq 2) { + push(@riglim, "--upper-limit=$NFSC6_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + push(@tmp, "AREA:calls#44EEEE:Calls"); + push(@tmp, "GPRINT:calls:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "AREA:retrans#EEEE44:Retransmissions"); + push(@tmp, "GPRINT:retrans:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "AREA:authref#EE4444:Auth Refresh"); + push(@tmp, "GPRINT:authref:LAST: Current\\: %7.1lf\\n"); + push(@tmp, "LINE1:calls#00EEEE"); + push(@tmp, "LINE1:retrans#EEEE00"); + push(@tmp, "LINE1:authref#EE0000"); + push(@tmpz, "AREA:calls#44EEEE:Calls"); + push(@tmpz, "AREA:retrans#EEEE44:Retransmissions"); + push(@tmpz, "AREA:authref#EE4444:Auth Refresh"); + push(@tmpz, "LINE1:calls#00EEEE"); + push(@tmpz, "LINE1:retrans#EEEE00"); + push(@tmpz, "LINE1:authref#EE0000"); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + RRDs::graph("$PNG_DIR" . "$PNG6", + "--title=$rgraphs{_nfsc6} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Requests/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:calls=$NFSC_RRD:nfsc_rpc_1:AVERAGE", + "DEF:retrans=$NFSC_RRD:nfsc_rpc_2:AVERAGE", + "DEF:authref=$NFSC_RRD:nfsc_rpc_3:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG6: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG6z", + "--title=$rgraphs{_nfsc6} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Requests/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:calls=$NFSC_RRD:nfsc_rpc_1:AVERAGE", + "DEF:retrans=$NFSC_RRD:nfsc_rpc_2:AVERAGE", + "DEF:authref=$NFSC_RRD:nfsc_rpc_3:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG6z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /nfsc6/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; +} + +# BIND graph +# ---------------------------------------------------------------------------- +sub bind { + my ($myself, $title) = @_; + + my $width; + my $height; + my @riglim; + my @PNG; + my @PNGz; + my @tmp; + my @tmpz; + my $e; + my $n; + my $str; + my $err; + my @LC = ( + "#FFA500", + "#4444EE", + "#EEEE44", + "#44EEEE", + "#EE44EE", + "#888888", + "#5F04B4", + "#44EE44", + "#448844", + "#EE4444", + "#444444", + "#E29136", + "#CCCCCC", + "#AEB404", + "#8A2908", + "#8C7000", + "#DDAE8C", + "#037C8C", + "#48D4D4", + "#9048D4", + ); + + if($IFACE_MODE eq "text") { + my $line0; + my $line1; + my $line2; + my $line3; + my $n2; + if($title) { + graph_header($title, 2); + print(" \n"); + print(" \n"); + } + my (undef, undef, undef, $data) = RRDs::fetch("$BIND_RRD", + "--start=-$nwhen$twhen", + "AVERAGE", + "-r $res"); + $err = RRDs::error; + print("ERROR: while fetching $BIND_RRD: $err\n") if $err; + print("
\n");
+		print("    ");
+		$line0 = "                                                                                                                                                $rgraphs{_bind1}                                                                                                                                                $rgraphs{_bind2}                                                                                                                                                                                                                                                                                                          $rgraphs{_bind3}                                                                                                                                                                                                                                                                                                  $rgraphs{_bind4}                                                                                                                                      $rgraphs{_bind5}                                           $rgraphs{_bind6}                     $rgraphs{_bind7}";
+		for($n = 0; $n < scalar(@BIND_URL_LIST); $n++) {
+			$line1 .= $line0;
+			$line3 .= "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------";
+			$n2 = 0;
+			foreach my $i (@BIND_IN_QUERIES_LIST[$n]) {
+				foreach(@$i) {
+					$str = sprintf("%7s", substr($_, 0, 7));
+					$line2 .= sprintf(" %7s", $str);
+					$n2++;
+				}
+			}
+			for(; $n2 < 20; $n2++) {
+				$str = sprintf("%7s", substr($_, 0, 7));
+				$line2 .= sprintf(" %7s", $str);
+			}
+
+			$n2 = 0;
+			foreach my $i (@BIND_OUT_QUERIES_LIST[$n]) {
+				foreach(@$i) {
+					$str = sprintf("%7s", substr($_, 0, 7));
+					$line2 .= sprintf(" %7s", $str);
+					$n2++;
+				}
+			}
+			for(; $n2 < 20; $n2++) {
+				$str = sprintf("%7s", substr($_, 0, 7));
+				$line2 .= sprintf(" %7s", $str);
+			}
+
+			$n2 = 0;
+			foreach my $i (@BIND_SERVER_STATS_LIST[$n]) {
+				foreach(@$i) {
+					$str = sprintf("%15s", substr($_, 0, 15));
+					$line2 .= sprintf(" %15s", $str);
+					$n2++;
+				}
+			}
+			for(; $n2 < 20; $n2++) {
+				$str = sprintf("%15s", substr($_, 0, 15));
+				$line2 .= sprintf(" %15s", $str);
+			}
+
+			$n2 = 0;
+			foreach my $i (@BIND_RESOLVER_STATS_LIST[$n]) {
+				foreach(@$i) {
+					$str = sprintf("%15s", substr($_, 0, 15));
+					$line2 .= sprintf(" %15s", $str);
+					$n2++;
+				}
+			}
+			for(; $n2 < 20; $n2++) {
+				$str = sprintf("%15s", substr($_, 0, 15));
+				$line2 .= sprintf(" %15s", $str);
+			}
+
+			$n2 = 0;
+			foreach my $i (@BIND_CACHE_RRSETS_LIST[$n]) {
+				foreach(@$i) {
+					$str = sprintf("%7s", substr($_, 0, 7));
+					$line2 .= sprintf(" %7s", $str);
+					$n2++;
+				}
+			}
+			for(; $n2 < 20; $n2++) {
+				$str = sprintf("%7s", substr($_, 0, 7));
+				$line2 .= sprintf(" %7s", $str);
+			}
+
+			foreach ("TotalUse", "InUse", "BlockSize", "ContxtSize", "Lost") {
+				$str = sprintf("%10s", substr($_, 0, 10));
+				$line2 .= sprintf(" %10s", $str);
+			}
+
+			foreach ("WorkerThds", "DefQuantum", "TasksRunng") {
+				$str = sprintf("%10s", substr($_, 0, 10));
+				$line2 .= sprintf(" %10s", $str);
+			}
+
+			$i = length($line0);
+			printf(sprintf("%${i}s", sprintf("BIND server: %s", $BIND_URL_LIST[$n])));
+		}
+		print("\n");
+		print("    $line1\n");
+		print("Time$line2 \n");
+		print("----$line3 \n");
+		my $line;
+		my @row;
+		my $time;
+		my $from;
+		my $to;
+		for($n = 0, $time = $tb; $n < ($tb * $ts); $n++) {
+			$line = @$data[$n];
+			$time = $time - (1 / $ts);
+			$from = 1;
+			printf(" %2d$tc ", $time);
+			for($n2 = 0; $n2 < scalar(@BIND_URL_LIST); $n2++) {
+				# inq
+				$from += $n2 * 95;
+				$to = $from + 20;
+				@row = @$line[$from..$to];
+				printf("%7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d ", @row);
+				# ouq
+				$from = $to;
+				$to = $from + 20;
+				@row = @$line[$from..$to];
+				printf("%7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d ", @row);
+				# ss
+				$from = $to;
+				$to = $from + 20;
+				@row = @$line[$from..$to];
+				printf("%15d %15d %15d %15d %15d %15d %15d %15d %15d %15d %15d %15d %15d %15d %15d %15d %15d %15d %15d %15d ", @row);
+				# rs
+				$from = $to;
+				$to = $from + 20;
+				@row = @$line[$from..$to];
+				printf("%15d %15d %15d %15d %15d %15d %15d %15d %15d %15d %15d %15d %15d %15d %15d %15d %15d %15d %15d %15d ", @row);
+				# crr
+				$from = $to;
+				$to = $from + 20;
+				@row = @$line[$from..$to];
+				printf("%7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d ", @row);
+				# mem
+				$from = $to;
+				$to = $from + 8;
+				@row = @$line[$from..$to];
+				printf("%10d %10d %10d %10d %10d ", @row);
+				# tsk
+				$from = $to;
+				$to = $from + 6;
+				@row = @$line[$from..$to];
+				printf("%10d %10d %10d ", @row);
+			}
+			print("\n");
+		}
+		print("    
\n"); + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; + } + + for($n = 0; $n < scalar(@BIND_URL_LIST); $n++) { + for($n2 = 1; $n2 <= 7; $n2++) { + $str = $u . $myself . $n . $n2 . "." . $when . ".png"; + push(@PNG, $str); + unlink("$PNG_DIR" . $str); + if($ENABLE_ZOOM eq "Y") { + $str = $u . $myself . $n . $n2 . "z." . $when . ".png"; + push(@PNGz, $str); + unlink("$PNG_DIR" . $str); + } + } + } + + $e = 0; + foreach my $host (@BIND_URL_LIST) { + if($e) { + print("
\n"); + } + if($title) { + graph_header($title, 2); + } + undef(@riglim); + if($BIND1_RIGID eq 1) { + push(@riglim, "--upper-limit=$BIND1_LIMIT"); + } else { + if($BIND1_RIGID eq 2) { + push(@riglim, "--upper-limit=$BIND1_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + my $i = $BIND_IN_QUERIES_LIST[$e]; + for($n = 0; $n < scalar(@$i); $n += 2) { + $str = sprintf("%-8s", substr(@$i[$n], 0, 8)); + push(@tmp, "LINE1:inq" . $n . $LC[$n] . ":$str"); + push(@tmp, "GPRINT:inq" . $n . ":LAST: Current\\:%5.1lf "); + push(@tmpz, "LINE2:inq" . $n . $LC[$n] . ":$str"); + $str = sprintf("%-8s", substr(@$i[$n + 1], 0, 8)); + push(@tmp, "LINE1:inq" . ($n + 1) . $LC[$n + 1] . ":$str"); + push(@tmp, "GPRINT:inq" . ($n + 1) . ":LAST: Current\\:%5.1lf\\n"); + push(@tmpz, "LINE2:inq" . ($n + 1) . $LC[$n + 1] . ":$str"); + } + for(; $n < 20; $n += 2) { + push(@tmp, "COMMENT: \\n"); + } + if($title) { + print(" \n"); + print(" \n"); + } + ($width, $height) = split('x', $GRAPH_SIZE{medium}); + RRDs::graph("$PNG_DIR" . "$PNG[$e * 7]", + "--title=$rgraphs{_bind1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Queries/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:inq0=$BIND_RRD:bind" . $e . "_inq01:AVERAGE", + "DEF:inq1=$BIND_RRD:bind" . $e . "_inq02:AVERAGE", + "DEF:inq2=$BIND_RRD:bind" . $e . "_inq03:AVERAGE", + "DEF:inq3=$BIND_RRD:bind" . $e . "_inq04:AVERAGE", + "DEF:inq4=$BIND_RRD:bind" . $e . "_inq05:AVERAGE", + "DEF:inq5=$BIND_RRD:bind" . $e . "_inq06:AVERAGE", + "DEF:inq6=$BIND_RRD:bind" . $e . "_inq07:AVERAGE", + "DEF:inq7=$BIND_RRD:bind" . $e . "_inq08:AVERAGE", + "DEF:inq8=$BIND_RRD:bind" . $e . "_inq09:AVERAGE", + "DEF:inq9=$BIND_RRD:bind" . $e . "_inq10:AVERAGE", + "DEF:inq10=$BIND_RRD:bind" . $e . "_inq11:AVERAGE", + "DEF:inq11=$BIND_RRD:bind" . $e . "_inq12:AVERAGE", + "DEF:inq12=$BIND_RRD:bind" . $e . "_inq13:AVERAGE", + "DEF:inq13=$BIND_RRD:bind" . $e . "_inq14:AVERAGE", + "DEF:inq14=$BIND_RRD:bind" . $e . "_inq15:AVERAGE", + "DEF:inq15=$BIND_RRD:bind" . $e . "_inq16:AVERAGE", + "DEF:inq16=$BIND_RRD:bind" . $e . "_inq17:AVERAGE", + "DEF:inq17=$BIND_RRD:bind" . $e . "_inq18:AVERAGE", + "DEF:inq18=$BIND_RRD:bind" . $e . "_inq19:AVERAGE", + "DEF:inq19=$BIND_RRD:bind" . $e . "_inq20:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG[$e * 7]: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNGz[$e * 7]", + "--title=$rgraphs{_bind1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Queries/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:inq0=$BIND_RRD:bind" . $e . "_inq01:AVERAGE", + "DEF:inq1=$BIND_RRD:bind" . $e . "_inq02:AVERAGE", + "DEF:inq2=$BIND_RRD:bind" . $e . "_inq03:AVERAGE", + "DEF:inq3=$BIND_RRD:bind" . $e . "_inq04:AVERAGE", + "DEF:inq4=$BIND_RRD:bind" . $e . "_inq05:AVERAGE", + "DEF:inq5=$BIND_RRD:bind" . $e . "_inq06:AVERAGE", + "DEF:inq6=$BIND_RRD:bind" . $e . "_inq07:AVERAGE", + "DEF:inq7=$BIND_RRD:bind" . $e . "_inq08:AVERAGE", + "DEF:inq8=$BIND_RRD:bind" . $e . "_inq09:AVERAGE", + "DEF:inq9=$BIND_RRD:bind" . $e . "_inq10:AVERAGE", + "DEF:inq10=$BIND_RRD:bind" . $e . "_inq11:AVERAGE", + "DEF:inq11=$BIND_RRD:bind" . $e . "_inq12:AVERAGE", + "DEF:inq12=$BIND_RRD:bind" . $e . "_inq13:AVERAGE", + "DEF:inq13=$BIND_RRD:bind" . $e . "_inq14:AVERAGE", + "DEF:inq14=$BIND_RRD:bind" . $e . "_inq15:AVERAGE", + "DEF:inq15=$BIND_RRD:bind" . $e . "_inq16:AVERAGE", + "DEF:inq16=$BIND_RRD:bind" . $e . "_inq17:AVERAGE", + "DEF:inq17=$BIND_RRD:bind" . $e . "_inq18:AVERAGE", + "DEF:inq18=$BIND_RRD:bind" . $e . "_inq19:AVERAGE", + "DEF:inq19=$BIND_RRD:bind" . $e . "_inq20:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNGz[$e * 7]: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /bind1/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + if($title) { + print(" \n"); + } + + undef(@riglim); + if($BIND2_RIGID eq 1) { + push(@riglim, "--upper-limit=$BIND2_LIMIT"); + } else { + if($BIND2_RIGID eq 2) { + push(@riglim, "--upper-limit=$BIND2_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + $i = $BIND_OUT_QUERIES_LIST[$e]; + for($n = 0; $n < scalar(@$i); $n += 2) { + $str = sprintf("%-8s", substr(@$i[$n], 0, 8)); + push(@tmp, "LINE1:ouq" . $n . $LC[$n] . ":$str"); + push(@tmp, "GPRINT:ouq" . $n . ":LAST: Current\\:%5.1lf "); + push(@tmpz, "LINE2:ouq" . $n . $LC[$n] . ":$str"); + $str = sprintf("%-8s", substr(@$i[$n + 1], 0, 8)); + push(@tmp, "LINE1:ouq" . ($n + 1) . $LC[$n + 1] . ":$str"); + push(@tmp, "GPRINT:ouq" . ($n + 1) . ":LAST: Current\\:%5.1lf\\n"); + push(@tmpz, "LINE2:ouq" . ($n + 1) . $LC[$n + 1] . ":$str"); + } + for(; $n < 20; $n += 2) { + push(@tmp, "COMMENT: \\n"); + } + if($title) { + print(" \n"); + } + ($width, $height) = split('x', $GRAPH_SIZE{medium}); + RRDs::graph("$PNG_DIR" . "$PNG[$e * 7 + 1]", + "--title=$rgraphs{_bind2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Queries/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:ouq0=$BIND_RRD:bind" . $e . "_ouq01:AVERAGE", + "DEF:ouq1=$BIND_RRD:bind" . $e . "_ouq02:AVERAGE", + "DEF:ouq2=$BIND_RRD:bind" . $e . "_ouq03:AVERAGE", + "DEF:ouq3=$BIND_RRD:bind" . $e . "_ouq04:AVERAGE", + "DEF:ouq4=$BIND_RRD:bind" . $e . "_ouq05:AVERAGE", + "DEF:ouq5=$BIND_RRD:bind" . $e . "_ouq06:AVERAGE", + "DEF:ouq6=$BIND_RRD:bind" . $e . "_ouq07:AVERAGE", + "DEF:ouq7=$BIND_RRD:bind" . $e . "_ouq08:AVERAGE", + "DEF:ouq8=$BIND_RRD:bind" . $e . "_ouq09:AVERAGE", + "DEF:ouq9=$BIND_RRD:bind" . $e . "_ouq10:AVERAGE", + "DEF:ouq10=$BIND_RRD:bind" . $e . "_ouq11:AVERAGE", + "DEF:ouq11=$BIND_RRD:bind" . $e . "_ouq12:AVERAGE", + "DEF:ouq12=$BIND_RRD:bind" . $e . "_ouq13:AVERAGE", + "DEF:ouq13=$BIND_RRD:bind" . $e . "_ouq14:AVERAGE", + "DEF:ouq14=$BIND_RRD:bind" . $e . "_ouq15:AVERAGE", + "DEF:ouq15=$BIND_RRD:bind" . $e . "_ouq16:AVERAGE", + "DEF:ouq16=$BIND_RRD:bind" . $e . "_ouq17:AVERAGE", + "DEF:ouq17=$BIND_RRD:bind" . $e . "_ouq18:AVERAGE", + "DEF:ouq18=$BIND_RRD:bind" . $e . "_ouq19:AVERAGE", + "DEF:ouq19=$BIND_RRD:bind" . $e . "_ouq20:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG[$e * 7 + 1]: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNGz[$e * 7 + 1]", + "--title=$rgraphs{_bind2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Queries/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:ouq0=$BIND_RRD:bind" . $e . "_ouq01:AVERAGE", + "DEF:ouq1=$BIND_RRD:bind" . $e . "_ouq02:AVERAGE", + "DEF:ouq2=$BIND_RRD:bind" . $e . "_ouq03:AVERAGE", + "DEF:ouq3=$BIND_RRD:bind" . $e . "_ouq04:AVERAGE", + "DEF:ouq4=$BIND_RRD:bind" . $e . "_ouq05:AVERAGE", + "DEF:ouq5=$BIND_RRD:bind" . $e . "_ouq06:AVERAGE", + "DEF:ouq6=$BIND_RRD:bind" . $e . "_ouq07:AVERAGE", + "DEF:ouq7=$BIND_RRD:bind" . $e . "_ouq08:AVERAGE", + "DEF:ouq8=$BIND_RRD:bind" . $e . "_ouq09:AVERAGE", + "DEF:ouq9=$BIND_RRD:bind" . $e . "_ouq10:AVERAGE", + "DEF:ouq10=$BIND_RRD:bind" . $e . "_ouq11:AVERAGE", + "DEF:ouq11=$BIND_RRD:bind" . $e . "_ouq12:AVERAGE", + "DEF:ouq12=$BIND_RRD:bind" . $e . "_ouq13:AVERAGE", + "DEF:ouq13=$BIND_RRD:bind" . $e . "_ouq14:AVERAGE", + "DEF:ouq14=$BIND_RRD:bind" . $e . "_ouq15:AVERAGE", + "DEF:ouq15=$BIND_RRD:bind" . $e . "_ouq16:AVERAGE", + "DEF:ouq16=$BIND_RRD:bind" . $e . "_ouq17:AVERAGE", + "DEF:ouq17=$BIND_RRD:bind" . $e . "_ouq18:AVERAGE", + "DEF:ouq18=$BIND_RRD:bind" . $e . "_ouq19:AVERAGE", + "DEF:ouq19=$BIND_RRD:bind" . $e . "_ouq20:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNGz[$e * 7 + 1]: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /bind2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@riglim); + if($BIND3_RIGID eq 1) { + push(@riglim, "--upper-limit=$BIND3_LIMIT"); + } else { + if($BIND3_RIGID eq 2) { + push(@riglim, "--upper-limit=$BIND3_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + $i = $BIND_SERVER_STATS_LIST[$e]; + for($n = 0; $n < scalar(@$i); $n += 2) { + $str = sprintf("%-14s", substr(@$i[$n], 0, 14)); + push(@tmp, "LINE1:ss" . $n . $LC[$n] . ":$str"); + push(@tmp, "GPRINT:ss" . $n . ":LAST:Cur\\:%5.1lf "); + push(@tmpz, "LINE2:ss" . $n . $LC[$n] . ":$str"); + $str = sprintf("%-14s", substr(@$i[$n + 1], 0, 14)); + push(@tmp, "LINE1:ss" . ($n + 1) . $LC[$n + 1] . ":$str"); + push(@tmp, "GPRINT:ss" . ($n + 1) . ":LAST:Cur\\:%5.1lf\\n"); + push(@tmpz, "LINE2:ss" . ($n + 1) . $LC[$n + 1] . ":$str"); + } + for(; $n < 20; $n += 2) { + push(@tmp, "COMMENT: \\n"); + } + if($title) { + print(" \n"); + print(" \n"); + } + ($width, $height) = split('x', $GRAPH_SIZE{medium}); + RRDs::graph("$PNG_DIR" . "$PNG[$e * 7 + 2]", + "--title=$rgraphs{_bind3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Requests/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:ss0=$BIND_RRD:bind" . $e . "_ss01:AVERAGE", + "DEF:ss1=$BIND_RRD:bind" . $e . "_ss02:AVERAGE", + "DEF:ss2=$BIND_RRD:bind" . $e . "_ss03:AVERAGE", + "DEF:ss3=$BIND_RRD:bind" . $e . "_ss04:AVERAGE", + "DEF:ss4=$BIND_RRD:bind" . $e . "_ss05:AVERAGE", + "DEF:ss5=$BIND_RRD:bind" . $e . "_ss06:AVERAGE", + "DEF:ss6=$BIND_RRD:bind" . $e . "_ss07:AVERAGE", + "DEF:ss7=$BIND_RRD:bind" . $e . "_ss08:AVERAGE", + "DEF:ss8=$BIND_RRD:bind" . $e . "_ss09:AVERAGE", + "DEF:ss9=$BIND_RRD:bind" . $e . "_ss10:AVERAGE", + "DEF:ss10=$BIND_RRD:bind" . $e . "_ss11:AVERAGE", + "DEF:ss11=$BIND_RRD:bind" . $e . "_ss12:AVERAGE", + "DEF:ss12=$BIND_RRD:bind" . $e . "_ss13:AVERAGE", + "DEF:ss13=$BIND_RRD:bind" . $e . "_ss14:AVERAGE", + "DEF:ss14=$BIND_RRD:bind" . $e . "_ss15:AVERAGE", + "DEF:ss15=$BIND_RRD:bind" . $e . "_ss16:AVERAGE", + "DEF:ss16=$BIND_RRD:bind" . $e . "_ss17:AVERAGE", + "DEF:ss17=$BIND_RRD:bind" . $e . "_ss18:AVERAGE", + "DEF:ss18=$BIND_RRD:bind" . $e . "_ss19:AVERAGE", + "DEF:ss19=$BIND_RRD:bind" . $e . "_ss20:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG[$e * 7 + 2]: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNGz[$e * 7 + 2]", + "--title=$rgraphs{_bind3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Requests/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:ss0=$BIND_RRD:bind" . $e . "_ss01:AVERAGE", + "DEF:ss1=$BIND_RRD:bind" . $e . "_ss02:AVERAGE", + "DEF:ss2=$BIND_RRD:bind" . $e . "_ss03:AVERAGE", + "DEF:ss3=$BIND_RRD:bind" . $e . "_ss04:AVERAGE", + "DEF:ss4=$BIND_RRD:bind" . $e . "_ss05:AVERAGE", + "DEF:ss5=$BIND_RRD:bind" . $e . "_ss06:AVERAGE", + "DEF:ss6=$BIND_RRD:bind" . $e . "_ss07:AVERAGE", + "DEF:ss7=$BIND_RRD:bind" . $e . "_ss08:AVERAGE", + "DEF:ss8=$BIND_RRD:bind" . $e . "_ss09:AVERAGE", + "DEF:ss9=$BIND_RRD:bind" . $e . "_ss10:AVERAGE", + "DEF:ss10=$BIND_RRD:bind" . $e . "_ss11:AVERAGE", + "DEF:ss11=$BIND_RRD:bind" . $e . "_ss12:AVERAGE", + "DEF:ss12=$BIND_RRD:bind" . $e . "_ss13:AVERAGE", + "DEF:ss13=$BIND_RRD:bind" . $e . "_ss14:AVERAGE", + "DEF:ss14=$BIND_RRD:bind" . $e . "_ss15:AVERAGE", + "DEF:ss15=$BIND_RRD:bind" . $e . "_ss16:AVERAGE", + "DEF:ss16=$BIND_RRD:bind" . $e . "_ss17:AVERAGE", + "DEF:ss17=$BIND_RRD:bind" . $e . "_ss18:AVERAGE", + "DEF:ss18=$BIND_RRD:bind" . $e . "_ss19:AVERAGE", + "DEF:ss19=$BIND_RRD:bind" . $e . "_ss20:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNGz[$e * 7 + 2]: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /bind3/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + if($title) { + print(" \n"); + } + + undef(@riglim); + if($BIND4_RIGID eq 1) { + push(@riglim, "--upper-limit=$BIND4_LIMIT"); + } else { + if($BIND4_RIGID eq 2) { + push(@riglim, "--upper-limit=$BIND4_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + $i = $BIND_RESOLVER_STATS_LIST[$e]; + for($n = 0; $n < scalar(@$i); $n += 2) { + $str = sprintf("%-14s", substr(@$i[$n], 0, 14)); + push(@tmp, "LINE1:rs" . $n . $LC[$n] . ":$str"); + push(@tmp, "GPRINT:rs" . $n . ":LAST:Cur\\:%5.1lf "); + push(@tmpz, "LINE2:rs" . $n . $LC[$n] . ":$str"); + $str = sprintf("%-14s", substr(@$i[$n + 1], 0, 14)); + push(@tmp, "LINE1:rs" . ($n + 1) . $LC[$n + 1] . ":$str"); + push(@tmp, "GPRINT:rs" . ($n + 1) . ":LAST:Cur\\:%5.1lf\\n"); + push(@tmpz, "LINE2:rs" . ($n + 1) . $LC[$n + 1] . ":$str"); + } + for(; $n < 20; $n += 2) { + push(@tmp, "COMMENT: \\n"); + } + if($title) { + print(" \n"); + } + ($width, $height) = split('x', $GRAPH_SIZE{medium}); + RRDs::graph("$PNG_DIR" . "$PNG[$e * 7 + 3]", + "--title=$rgraphs{_bind4} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Requests/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:rs0=$BIND_RRD:bind" . $e . "_rs01:AVERAGE", + "DEF:rs1=$BIND_RRD:bind" . $e . "_rs02:AVERAGE", + "DEF:rs2=$BIND_RRD:bind" . $e . "_rs03:AVERAGE", + "DEF:rs3=$BIND_RRD:bind" . $e . "_rs04:AVERAGE", + "DEF:rs4=$BIND_RRD:bind" . $e . "_rs05:AVERAGE", + "DEF:rs5=$BIND_RRD:bind" . $e . "_rs06:AVERAGE", + "DEF:rs6=$BIND_RRD:bind" . $e . "_rs07:AVERAGE", + "DEF:rs7=$BIND_RRD:bind" . $e . "_rs08:AVERAGE", + "DEF:rs8=$BIND_RRD:bind" . $e . "_rs09:AVERAGE", + "DEF:rs9=$BIND_RRD:bind" . $e . "_rs10:AVERAGE", + "DEF:rs10=$BIND_RRD:bind" . $e . "_rs11:AVERAGE", + "DEF:rs11=$BIND_RRD:bind" . $e . "_rs12:AVERAGE", + "DEF:rs12=$BIND_RRD:bind" . $e . "_rs13:AVERAGE", + "DEF:rs13=$BIND_RRD:bind" . $e . "_rs14:AVERAGE", + "DEF:rs14=$BIND_RRD:bind" . $e . "_rs15:AVERAGE", + "DEF:rs15=$BIND_RRD:bind" . $e . "_rs16:AVERAGE", + "DEF:rs16=$BIND_RRD:bind" . $e . "_rs17:AVERAGE", + "DEF:rs17=$BIND_RRD:bind" . $e . "_rs18:AVERAGE", + "DEF:rs18=$BIND_RRD:bind" . $e . "_rs19:AVERAGE", + "DEF:rs19=$BIND_RRD:bind" . $e . "_rs20:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG[$e * 7 + 3]: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNGz[$e * 7 + 3]", + "--title=$rgraphs{_bind4} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Requests/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:rs0=$BIND_RRD:bind" . $e . "_rs01:AVERAGE", + "DEF:rs1=$BIND_RRD:bind" . $e . "_rs02:AVERAGE", + "DEF:rs2=$BIND_RRD:bind" . $e . "_rs03:AVERAGE", + "DEF:rs3=$BIND_RRD:bind" . $e . "_rs04:AVERAGE", + "DEF:rs4=$BIND_RRD:bind" . $e . "_rs05:AVERAGE", + "DEF:rs5=$BIND_RRD:bind" . $e . "_rs06:AVERAGE", + "DEF:rs6=$BIND_RRD:bind" . $e . "_rs07:AVERAGE", + "DEF:rs7=$BIND_RRD:bind" . $e . "_rs08:AVERAGE", + "DEF:rs8=$BIND_RRD:bind" . $e . "_rs09:AVERAGE", + "DEF:rs9=$BIND_RRD:bind" . $e . "_rs10:AVERAGE", + "DEF:rs10=$BIND_RRD:bind" . $e . "_rs11:AVERAGE", + "DEF:rs11=$BIND_RRD:bind" . $e . "_rs12:AVERAGE", + "DEF:rs12=$BIND_RRD:bind" . $e . "_rs13:AVERAGE", + "DEF:rs13=$BIND_RRD:bind" . $e . "_rs14:AVERAGE", + "DEF:rs14=$BIND_RRD:bind" . $e . "_rs15:AVERAGE", + "DEF:rs15=$BIND_RRD:bind" . $e . "_rs16:AVERAGE", + "DEF:rs16=$BIND_RRD:bind" . $e . "_rs17:AVERAGE", + "DEF:rs17=$BIND_RRD:bind" . $e . "_rs18:AVERAGE", + "DEF:rs18=$BIND_RRD:bind" . $e . "_rs19:AVERAGE", + "DEF:rs19=$BIND_RRD:bind" . $e . "_rs20:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNGz[$e * 7 + 3]: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /bind4/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@riglim); + if($BIND5_RIGID eq 1) { + push(@riglim, "--upper-limit=$BIND5_LIMIT"); + } else { + if($BIND5_RIGID eq 2) { + push(@riglim, "--upper-limit=$BIND5_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + $i = $BIND_CACHE_RRSETS_LIST[$e]; + for($n = 0; $n < scalar(@$i); $n += 2) { + $str = sprintf("%-8s", substr(@$i[$n], 0, 8)); + push(@tmp, "LINE1:crr" . $n . $LC[$n] . ":$str"); + push(@tmp, "GPRINT:crr" . $n . ":LAST: Cur\\:%8.1lf "); + push(@tmpz, "LINE2:crr" . $n . $LC[$n] . ":$str"); + $str = sprintf("%-8s", substr(@$i[$n + 1], 0, 8)); + push(@tmp, "LINE1:crr" . ($n + 1) . $LC[$n + 1] . ":$str"); + push(@tmp, "GPRINT:crr" . ($n + 1) . ":LAST: Cur\\:%8.1lf\\n"); + push(@tmpz, "LINE2:crr" . ($n + 1) . $LC[$n + 1] . ":$str"); + } + for(; $n < 20; $n += 2) { + push(@tmp, "COMMENT: \\n"); + } + if($title) { + print(" \n"); + print(" \n"); + } + ($width, $height) = split('x', $GRAPH_SIZE{medium}); + RRDs::graph("$PNG_DIR" . "$PNG[$e * 7 + 4]", + "--title=$rgraphs{_bind5} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=RRsets", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:crr0=$BIND_RRD:bind" . $e . "_crr01:AVERAGE", + "DEF:crr1=$BIND_RRD:bind" . $e . "_crr02:AVERAGE", + "DEF:crr2=$BIND_RRD:bind" . $e . "_crr03:AVERAGE", + "DEF:crr3=$BIND_RRD:bind" . $e . "_crr04:AVERAGE", + "DEF:crr4=$BIND_RRD:bind" . $e . "_crr05:AVERAGE", + "DEF:crr5=$BIND_RRD:bind" . $e . "_crr06:AVERAGE", + "DEF:crr6=$BIND_RRD:bind" . $e . "_crr07:AVERAGE", + "DEF:crr7=$BIND_RRD:bind" . $e . "_crr08:AVERAGE", + "DEF:crr8=$BIND_RRD:bind" . $e . "_crr09:AVERAGE", + "DEF:crr9=$BIND_RRD:bind" . $e . "_crr10:AVERAGE", + "DEF:crr10=$BIND_RRD:bind" . $e . "_crr11:AVERAGE", + "DEF:crr11=$BIND_RRD:bind" . $e . "_crr12:AVERAGE", + "DEF:crr12=$BIND_RRD:bind" . $e . "_crr13:AVERAGE", + "DEF:crr13=$BIND_RRD:bind" . $e . "_crr14:AVERAGE", + "DEF:crr14=$BIND_RRD:bind" . $e . "_crr15:AVERAGE", + "DEF:crr15=$BIND_RRD:bind" . $e . "_crr16:AVERAGE", + "DEF:crr16=$BIND_RRD:bind" . $e . "_crr17:AVERAGE", + "DEF:crr17=$BIND_RRD:bind" . $e . "_crr18:AVERAGE", + "DEF:crr18=$BIND_RRD:bind" . $e . "_crr19:AVERAGE", + "DEF:crr19=$BIND_RRD:bind" . $e . "_crr20:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG[$e * 7 + 4]: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNGz[$e * 7 + 4]", + "--title=$rgraphs{_bind5} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=RRsets", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:crr0=$BIND_RRD:bind" . $e . "_crr01:AVERAGE", + "DEF:crr1=$BIND_RRD:bind" . $e . "_crr02:AVERAGE", + "DEF:crr2=$BIND_RRD:bind" . $e . "_crr03:AVERAGE", + "DEF:crr3=$BIND_RRD:bind" . $e . "_crr04:AVERAGE", + "DEF:crr4=$BIND_RRD:bind" . $e . "_crr05:AVERAGE", + "DEF:crr5=$BIND_RRD:bind" . $e . "_crr06:AVERAGE", + "DEF:crr6=$BIND_RRD:bind" . $e . "_crr07:AVERAGE", + "DEF:crr7=$BIND_RRD:bind" . $e . "_crr08:AVERAGE", + "DEF:crr8=$BIND_RRD:bind" . $e . "_crr09:AVERAGE", + "DEF:crr9=$BIND_RRD:bind" . $e . "_crr10:AVERAGE", + "DEF:crr10=$BIND_RRD:bind" . $e . "_crr11:AVERAGE", + "DEF:crr11=$BIND_RRD:bind" . $e . "_crr12:AVERAGE", + "DEF:crr12=$BIND_RRD:bind" . $e . "_crr13:AVERAGE", + "DEF:crr13=$BIND_RRD:bind" . $e . "_crr14:AVERAGE", + "DEF:crr14=$BIND_RRD:bind" . $e . "_crr15:AVERAGE", + "DEF:crr15=$BIND_RRD:bind" . $e . "_crr16:AVERAGE", + "DEF:crr16=$BIND_RRD:bind" . $e . "_crr17:AVERAGE", + "DEF:crr17=$BIND_RRD:bind" . $e . "_crr18:AVERAGE", + "DEF:crr18=$BIND_RRD:bind" . $e . "_crr19:AVERAGE", + "DEF:crr19=$BIND_RRD:bind" . $e . "_crr20:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNGz[$e * 7 + 4]: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /bind5/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + if($title) { + print(" \n"); + } + + undef(@tmp); + undef(@tmpz); + push(@tmp, "LINE1:mem_tu#EEEE44:TotalUse"); + push(@tmp, "GPRINT:mem_tu_mb" . ":LAST: Cur\\:%6.1lf MB "); + push(@tmpz, "LINE2:mem_tu#EEEE44:TotalUse"); + push(@tmp, "LINE1:mem_iu#4444EE:InUse"); + push(@tmp, "GPRINT:mem_iu_mb" . ":LAST: Cur\\:%5.1lf MB\\n"); + push(@tmpz, "LINE2:mem_iu#4444EE:InUse"); + push(@tmp, "LINE1:mem_bs#44EEEE:BlockSize"); + push(@tmp, "GPRINT:mem_bs_mb" . ":LAST:Cur\\:%6.1lf MB "); + push(@tmpz, "LINE2:mem_bs#44EEEE:BlockSize"); + push(@tmp, "LINE1:mem_cs#EE44EE:ContextSize"); + push(@tmp, "GPRINT:mem_cs_mb" . ":LAST:Cur\\:%5.1lf MB\\n"); + push(@tmpz, "LINE2:mem_cs#EE44EE:ContextSize"); + push(@tmp, "LINE1:mem_l#EE4444:Lost"); + push(@tmp, "GPRINT:mem_l_mb" . ":LAST: Cur\\:%6.1lf MB\\n"); + push(@tmpz, "LINE2:mem_l#EE4444:Lost"); + if($title) { + print(" \n"); + } + ($width, $height) = split('x', $GRAPH_SIZE{medium2}); + RRDs::graph("$PNG_DIR" . "$PNG[$e * 7 + 5]", + "--title=$rgraphs{_bind6} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=bytes", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:mem_tu=$BIND_RRD:bind" . $e . "_mem_totaluse:AVERAGE", + "DEF:mem_iu=$BIND_RRD:bind" . $e . "_mem_inuse:AVERAGE", + "DEF:mem_bs=$BIND_RRD:bind" . $e . "_mem_blksize:AVERAGE", + "DEF:mem_cs=$BIND_RRD:bind" . $e . "_mem_ctxtsize:AVERAGE", + "DEF:mem_l=$BIND_RRD:bind" . $e . "_mem_lost:AVERAGE", + "CDEF:mem_tu_mb=mem_tu,1024,/,1024,/", + "CDEF:mem_iu_mb=mem_iu,1024,/,1024,/", + "CDEF:mem_bs_mb=mem_bs,1024,/,1024,/", + "CDEF:mem_cs_mb=mem_cs,1024,/,1024,/", + "CDEF:mem_l_mb=mem_l,1024,/,1024,/", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG[$e * 7 + 5]: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNGz[$e * 7 + 5]", + "--title=$rgraphs{_bind6} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=bytes", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:mem_tu=$BIND_RRD:bind" . $e . "_mem_totaluse:AVERAGE", + "DEF:mem_iu=$BIND_RRD:bind" . $e . "_mem_inuse:AVERAGE", + "DEF:mem_bs=$BIND_RRD:bind" . $e . "_mem_blksize:AVERAGE", + "DEF:mem_cs=$BIND_RRD:bind" . $e . "_mem_ctxtsize:AVERAGE", + "DEF:mem_l=$BIND_RRD:bind" . $e . "_mem_lost:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNGz[$e * 7 + 5]: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /bind6/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@tmp); + undef(@tmpz); + push(@tmp, "LINE1:tsk_dq#EEEE44:Default Quantum"); + push(@tmp, "GPRINT:tsk_dq" . ":LAST: Current\\:%4.0lf\\n"); + push(@tmpz, "LINE2:tsk_dq#EEEE44:Default Quantum"); + push(@tmp, "LINE1:tsk_wt#4444EE:Worker Threads"); + push(@tmp, "GPRINT:tsk_wt" . ":LAST: Current\\:%4.0lf\\n"); + push(@tmpz, "LINE2:tsk_wt#4444EE:Worker Threads"); + push(@tmp, "LINE1:tsk_tr#44EEEE:Tasks Running"); + push(@tmp, "GPRINT:tsk_tr" . ":LAST: Current\\:%4.0lf\\n"); + push(@tmpz, "LINE2:tsk_tr#44EEEE:Tasks Running"); + ($width, $height) = split('x', $GRAPH_SIZE{medium2}); + RRDs::graph("$PNG_DIR" . "$PNG[$e * 7 + 6]", + "--title=$rgraphs{_bind7} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Tasks", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:tsk_wt=$BIND_RRD:bind" . $e . "_tsk_workthrds:AVERAGE", + "DEF:tsk_dq=$BIND_RRD:bind" . $e . "_tsk_defquantm:AVERAGE", + "DEF:tsk_tr=$BIND_RRD:bind" . $e . "_tsk_tasksrun:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG[$e * 7 + 6]: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNGz[$e * 7 + 6]", + "--title=$rgraphs{_bind7} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Tasks", + "--width=$width", + "--height=$height", + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:tsk_wt=$BIND_RRD:bind" . $e . "_tsk_workthrds:AVERAGE", + "DEF:tsk_dq=$BIND_RRD:bind" . $e . "_tsk_defquantm:AVERAGE", + "DEF:tsk_tr=$BIND_RRD:bind" . $e . "_tsk_tasksrun:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNGz[$e * 7 + 6]: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /bind7/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + if($title) { + print(" \n"); + print(" \n"); + + print(" \n"); + print " \n"; + print " \n"; + print " \n"; + print "   $host\n"; + print " \n"; + print " \n"; + print(" \n"); + graph_footer(); + } + $e++; + } + return 1; +} + +# NTP graph +# ---------------------------------------------------------------------------- +sub ntp { + my ($myself, $title) = @_; + + my $width; + my $height; + my @riglim; + my @PNG; + my @PNGz; + my @tmp; + my @tmpz; + my $e; + my $e2; + my $n; + my $n2; + my $str; + my $err; + my @AC = ( + "#FFA500", + "#44EEEE", + "#44EE44", + "#4444EE", + "#448844", + "#EE4444", + "#EE44EE", + "#EEEE44", + "#B4B444", + "#444444", + ); + + $title = !$silent ? $title : ""; + + if($IFACE_MODE eq "text") { + my $line1; + my $line2; + my $line3; + if($title) { + graph_header($title, 2); + print(" \n"); + print(" \n"); + } + my (undef, undef, undef, $data) = RRDs::fetch("$NTP_RRD", + "--start=-$nwhen$twhen", + "AVERAGE", + "-r $res"); + $err = RRDs::error; + print("ERROR: while fetching $NTP_RRD: $err\n") if $err; + print("
\n");
+		print("    ");
+		for($n = 0; $n < scalar(@NTP_HOST_LIST); $n++) {
+			$line1 = "                                  ";
+			$line2 .= "     Delay   Offset   Jitter   Str";
+			$line3 .= "----------------------------------";
+			foreach my $i (@NTP_CODE_LIST[$n]) {
+				foreach(@$i) {
+					$line1 .= "     ";
+					$line2 .= sprintf(" %4s", $_);
+					$line3 .= "-----";
+				}
+			}
+			if($line1) {
+				$i = length($line1);
+				printf(sprintf("%${i}s", sprintf("NTP Server: %s", $NTP_HOST_LIST[$n])));
+			}
+		}
+		print("\n");
+		print("Time$line2\n");
+		print("----$line3 \n");
+		my $line;
+		my @row;
+		my $time;
+		my $n2;
+		my $n3;
+		my $from;
+		my $to;
+		for($n = 0, $time = $tb; $n < ($tb * $ts); $n++) {
+			$line = @$data[$n];
+			$time = $time - (1 / $ts);
+			printf(" %2d$tc", $time);
+			for($n2 = 0; $n2 < scalar(@NTP_HOST_LIST); $n2++) {
+				undef(@row);
+				$from = $n2 * 14;
+				$to = $from + 4;
+				push(@row, @$line[$from..$to]);
+				printf("  %8.3f %8.3f %8.3f   %2d ", @row);
+				foreach my $i (@NTP_CODE_LIST[$n2]) {
+					for($n3 = 0; $n3 < scalar(@$i); $n3++) {
+						$from = $n2 * 14 + 4 + $n3;
+						my ($c) = @$line[$from];
+						printf(" %4d", $c);
+					}
+				}
+			}
+			print("\n");
+		}
+		print("    
\n"); + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; + } + + for($n = 0; $n < scalar(@NTP_HOST_LIST); $n++) { + for($n2 = 1; $n2 <= 3; $n2++) { + $str = $u . $myself . $n . $n2 . "." . $when . ".png"; + push(@PNG, $str); + unlink("$PNG_DIR" . $str); + if($ENABLE_ZOOM eq "Y") { + $str = $u . $myself . $n . $n2 . "z." . $when . ".png"; + push(@PNGz, $str); + unlink("$PNG_DIR" . $str); + } + } + } + + $e = 0; + foreach my $host (@NTP_HOST_LIST) { + if($e) { + print("
\n"); + } + if($title) { + graph_header($title, 2); + } + undef(@riglim); + if($NTP1_RIGID eq 1) { + push(@riglim, "--upper-limit=$NTP1_LIMIT"); + } else { + if($NTP1_RIGID eq 2) { + push(@riglim, "--upper-limit=$NTP1_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + push(@tmp, "LINE2:ntp" . $e . "_del#4444EE:Delay"); + push(@tmp, "GPRINT:ntp" . $e . "_del" . ":LAST: Current\\:%6.3lf"); + push(@tmp, "GPRINT:ntp" . $e . "_del" . ":AVERAGE: Average\\:%6.3lf"); + push(@tmp, "GPRINT:ntp" . $e . "_del" . ":MIN: Min\\:%6.3lf"); + push(@tmp, "GPRINT:ntp" . $e . "_del" . ":MAX: Max\\:%6.3lf\\n"); + push(@tmp, "LINE2:ntp" . $e . "_off#44EEEE:Offset"); + push(@tmp, "GPRINT:ntp" . $e . "_off" . ":LAST: Current\\:%6.3lf"); + push(@tmp, "GPRINT:ntp" . $e . "_off" . ":AVERAGE: Average\\:%6.3lf"); + push(@tmp, "GPRINT:ntp" . $e . "_off" . ":MIN: Min\\:%6.3lf"); + push(@tmp, "GPRINT:ntp" . $e . "_off" . ":MAX: Max\\:%6.3lf\\n"); + push(@tmp, "LINE2:ntp" . $e . "_jit#EE4444:Jitter"); + push(@tmp, "GPRINT:ntp" . $e . "_jit" . ":LAST: Current\\:%6.3lf"); + push(@tmp, "GPRINT:ntp" . $e . "_jit" . ":AVERAGE: Average\\:%6.3lf"); + push(@tmp, "GPRINT:ntp" . $e . "_jit" . ":MIN: Min\\:%6.3lf"); + push(@tmp, "GPRINT:ntp" . $e . "_jit" . ":MAX: Max\\:%6.3lf\\n"); + push(@tmpz, "LINE2:ntp" . $e . "_del#4444EE:Delay"); + push(@tmpz, "LINE2:ntp" . $e . "_off#44EEEE:Offset"); + push(@tmpz, "LINE2:ntp" . $e . "_jit#EE4444:Jitter"); + if($title) { + print(" \n"); + print(" \n"); + } + ($width, $height) = split('x', $GRAPH_SIZE{main}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + } + RRDs::graph("$PNG_DIR" . "$PNG[$e * 3]", + "--title=$rgraphs{_ntp1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Seconds", + "--width=$width", + "--height=$height", + @riglim, + @VERSION12, + @graph_colors, + "DEF:ntp" . $e . "_del=$NTP_RRD:ntp" . $e . "_del:AVERAGE", + "DEF:ntp" . $e . "_off=$NTP_RRD:ntp" . $e . "_off:AVERAGE", + "DEF:ntp" . $e . "_jit=$NTP_RRD:ntp" . $e . "_jit:AVERAGE", + "COMMENT: \\n", + @tmp, + "COMMENT: \\n", + "COMMENT: \\n",); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG[$e * 3]: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNGz[$e * 3]", + "--title=$rgraphs{_ntp1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Seconds", + "--width=$width", + "--height=$height", + @riglim, + @VERSION12, + @graph_colors, + "DEF:ntp" . $e . "_del=$NTP_RRD:ntp" . $e . "_del:AVERAGE", + "DEF:ntp" . $e . "_off=$NTP_RRD:ntp" . $e . "_off:AVERAGE", + "DEF:ntp" . $e . "_jit=$NTP_RRD:ntp" . $e . "_jit:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNGz[$e * 3]: $err\n") if $err; + } + $e2 = $e + 1; + if($title || ($silent =~ /imagetag/ && $graph =~ /ntp$e2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + if($title) { + print(" \n"); + print(" \n"); + } + + undef(@riglim); + if($NTP2_RIGID eq 1) { + push(@riglim, "--upper-limit=$NTP2_LIMIT"); + } else { + if($NTP2_RIGID eq 2) { + push(@riglim, "--upper-limit=$NTP2_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + push(@tmp, "LINE2:ntp" . $e . "_str#44EEEE:Stratum"); + push(@tmp, "GPRINT:ntp" . $e . "_str" . ":LAST: Current\\:%2.0lf\\n"); + push(@tmpz, "LINE2:ntp" . $e . "_str#44EEEE:Stratum"); + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + } + RRDs::graph("$PNG_DIR" . $PNG[$e * 3 + 1], + "--title=$rgraphs{_ntp2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Level", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:ntp" . $e . "_str=$NTP_RRD:ntp" . $e . "_str:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . $PNG[$e * 3 + 1] . ": $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . $PNGz[$e * 3 + 1], + "--title=$rgraphs{_ntp2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Level", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:ntp" . $e . "_str=$NTP_RRD:ntp" . $e . "_str:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . $PNGz[$e * 3 + 1] . ": $err\n") if $err; + } + $e2 = $e + 2; + if($title || ($silent =~ /imagetag/ && $graph =~ /ntp$e2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@tmp); + undef(@tmpz); + $i = @NTP_CODE_LIST[$e]; + for($n = 0; $n < 10; $n++) { + if(@$i[$n]) { + $str = sprintf("%-4s", @$i[$n]); + push(@tmp, "LINE2:ntp" . $e . "_c" . sprintf("%02d", ($n + 1)) . $AC[$n] . ":$str"); + push(@tmp, "COMMENT: \\g"); + push(@tmpz, "LINE2:ntp" . $e . "_c" . sprintf("%02d", ($n + 1)) . $AC[$n] . ":$str"); + if(!(($n + 1) % 5)) { + push(@tmp, ("COMMENT: \\n")); + } + } + } + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + } + RRDs::graph("$PNG_DIR" . $PNG[$e * 3 + 2], + "--title=$rgraphs{_ntp3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Hits", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:ntp" . $e . "_c01=$NTP_RRD:ntp" . $e . "_c01:AVERAGE", + "DEF:ntp" . $e . "_c02=$NTP_RRD:ntp" . $e . "_c02:AVERAGE", + "DEF:ntp" . $e . "_c03=$NTP_RRD:ntp" . $e . "_c03:AVERAGE", + "DEF:ntp" . $e . "_c04=$NTP_RRD:ntp" . $e . "_c04:AVERAGE", + "DEF:ntp" . $e . "_c05=$NTP_RRD:ntp" . $e . "_c05:AVERAGE", + "DEF:ntp" . $e . "_c06=$NTP_RRD:ntp" . $e . "_c06:AVERAGE", + "DEF:ntp" . $e . "_c07=$NTP_RRD:ntp" . $e . "_c07:AVERAGE", + "DEF:ntp" . $e . "_c08=$NTP_RRD:ntp" . $e . "_c08:AVERAGE", + "DEF:ntp" . $e . "_c09=$NTP_RRD:ntp" . $e . "_c09:AVERAGE", + "DEF:ntp" . $e . "_c10=$NTP_RRD:ntp" . $e . "_c10:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . $PNG[$e * 3 + 2] . ": $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . $PNGz[$e * 3 + 2], + "--title=$rgraphs{_ntp3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Hits", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:ntp" . $e . "_c01=$NTP_RRD:ntp" . $e . "_c01:AVERAGE", + "DEF:ntp" . $e . "_c02=$NTP_RRD:ntp" . $e . "_c02:AVERAGE", + "DEF:ntp" . $e . "_c03=$NTP_RRD:ntp" . $e . "_c03:AVERAGE", + "DEF:ntp" . $e . "_c04=$NTP_RRD:ntp" . $e . "_c04:AVERAGE", + "DEF:ntp" . $e . "_c05=$NTP_RRD:ntp" . $e . "_c05:AVERAGE", + "DEF:ntp" . $e . "_c06=$NTP_RRD:ntp" . $e . "_c06:AVERAGE", + "DEF:ntp" . $e . "_c07=$NTP_RRD:ntp" . $e . "_c07:AVERAGE", + "DEF:ntp" . $e . "_c08=$NTP_RRD:ntp" . $e . "_c08:AVERAGE", + "DEF:ntp" . $e . "_c09=$NTP_RRD:ntp" . $e . "_c09:AVERAGE", + "DEF:ntp" . $e . "_c10=$NTP_RRD:ntp" . $e . "_c10:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . $PNGz[$e * 3 + 2] . ": $err\n") if $err; + } + $e2 = $e + 3; + if($title || ($silent =~ /imagetag/ && $graph =~ /ntp$e2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + if($title) { + print(" \n"); + print(" \n"); + + print(" \n"); + print " \n"; + print " \n"; + print " \n"; + print "   $host\n"; + print " \n"; + print " \n"; + print(" \n"); + graph_footer(); + } + $e++; + } + return 1; +} + +# FAIL2BAN graph +# ---------------------------------------------------------------------------- +sub fail2ban { + my ($myself, $title) = @_; + + my $width; + my $height; + my @riglim; + my @PNG; + my @PNGz; + my @tmp; + my @tmpz; + my $n; + my $str; + my $err; + my @LC = ( + "#4444EE", + "#EEEE44", + "#44EEEE", + "#EE44EE", + "#888888", + "#E29136", + "#44EE44", + "#448844", + "#EE4444", + ); + + if($IFACE_MODE eq "text") { + my $line1; + my $line2; + my $line3; + if($title) { + graph_header($title, 2); + print(" \n"); + print(" \n"); + } + my (undef, undef, undef, $data) = RRDs::fetch("$FAIL2BAN_RRD", + "--start=-$nwhen$twhen", + "AVERAGE", + "-r $res"); + $err = RRDs::error; + print("ERROR: while fetching $FAIL2BAN_RRD: $err\n") if $err; + print("
\n");
+		print("    ");
+		for($n = 0; $n < scalar(@FAIL2BAN_LIST); $n++) {
+			$line1 = "";
+			foreach my $i (@FAIL2BAN_LIST[$n]) {
+				foreach(@$i) {
+					$str = sprintf("%20s", substr($_, 0, 20));
+					$line1 .= "                     ";
+					$line2 .= sprintf(" %20s", $str);
+					$line3 .= "---------------------";
+				}
+			}
+			if($line1) {
+				$i = length($line1);
+				printf(sprintf("%${i}s", sprintf("%s", $FAIL2BAN_DESC[$n])));
+			}
+		}
+		print("\n");
+		print("Time$line2\n");
+		print("----$line3 \n");
+		my $line;
+		my @row;
+		my $time;
+		my $n2;
+		my $n3;
+		my $from;
+		my $to;
+		for($n = 0, $time = $tb; $n < ($tb * $ts); $n++) {
+			$line = @$data[$n];
+			$time = $time - (1 / $ts);
+			printf(" %2d$tc ", $time);
+			for($n2 = 0; $n2 < scalar(@FAIL2BAN_LIST); $n2++) {
+				foreach my $i (@FAIL2BAN_LIST[$n2]) {
+					for($n3 = 0; $n3 < scalar(@$i); $n3++) {
+						$from = $n2 * 9 + $n3;
+						$to = $from + 1;
+						my ($j) = @$line[$from..$to];
+						@row = ($j);
+						printf("%20d ", @row);
+					}
+				}
+			}
+			print("\n");
+		}
+		print("    
\n"); + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; + } + + for($n = 0; $n < scalar(@FAIL2BAN_LIST); $n++) { + $str = $u . $myself . $n . "." . $when . ".png"; + push(@PNG, $str); + unlink("$PNG_DIR" . $str); + if($ENABLE_ZOOM eq "Y") { + $str = $u . $myself . $n . "z." . $when . ".png"; + push(@PNGz, $str); + unlink("$PNG_DIR" . $str); + } + } + + if($FAIL2BAN_RIGID eq 1) { + push(@riglim, "--upper-limit=$FAIL2BAN_LIMIT"); + } else { + if($FAIL2BAN_RIGID eq 2) { + push(@riglim, "--upper-limit=$FAIL2BAN_LIMIT"); + push(@riglim, "--rigid"); + } + } + $n = 0; + while($n < scalar(@FAIL2BAN_LIST)) { + if($title) { + if($n == 0) { + graph_header($title, $FAIL2BAN_PER_ROW); + } + print(" \n"); + } + for($n2 = 0; $n2 < $FAIL2BAN_PER_ROW; $n2++) { + last unless $n < scalar(@FAIL2BAN_LIST); + if($title) { + print(" \n"); + } + undef(@tmp); + undef(@tmpz); + foreach my $i ($FAIL2BAN_LIST[$n]) { + my $e = 0; + foreach(@$i) { + $str = sprintf("%-25s", substr($_, 0, 25)); + push(@tmp, "LINE1:j" . ($e + 1) . $LC[$e] . ":$str"); + push(@tmp, "GPRINT:j" . ($e + 1) . ":LAST: Cur\\:%2.0lf\\g"); + push(@tmp, "GPRINT:j" . ($e + 1) . ":AVERAGE: Avg\\:%2.0lf\\g"); + push(@tmp, "GPRINT:j" . ($e + 1) . ":MIN: Min\\:%2.0lf\\g"); + push(@tmp, "GPRINT:j" . ($e + 1) . ":MAX: Max\\:%2.0lf\\n"); + push(@tmpz, "LINE2:j" . ($e + 1) . $LC[$e] . ":$str"); + $e++; + } + for($e = scalar(@$i); $e < 9; $e++) { + push(@tmp, "COMMENT: \\n"); + } + } + ($width, $height) = split('x', $GRAPH_SIZE{medium}); + $str = substr($FAIL2BAN_DESC[$n2], 0, 25); + RRDs::graph("$PNG_DIR" . "$PNG[$n]", + "--title=$str ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=bans/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:j1=$FAIL2BAN_RRD:fail2ban" . $n . "_j1:AVERAGE", + "DEF:j2=$FAIL2BAN_RRD:fail2ban" . $n . "_j2:AVERAGE", + "DEF:j3=$FAIL2BAN_RRD:fail2ban" . $n . "_j3:AVERAGE", + "DEF:j4=$FAIL2BAN_RRD:fail2ban" . $n . "_j4:AVERAGE", + "DEF:j5=$FAIL2BAN_RRD:fail2ban" . $n . "_j5:AVERAGE", + "DEF:j6=$FAIL2BAN_RRD:fail2ban" . $n . "_j6:AVERAGE", + "DEF:j7=$FAIL2BAN_RRD:fail2ban" . $n . "_j7:AVERAGE", + "DEF:j8=$FAIL2BAN_RRD:fail2ban" . $n . "_j8:AVERAGE", + "DEF:j9=$FAIL2BAN_RRD:fail2ban" . $n . "_j9:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG[$n]: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNGz[$n]", + "--title=$str ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=bans/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:j1=$FAIL2BAN_RRD:fail2ban" . $n . "_j1:AVERAGE", + "DEF:j2=$FAIL2BAN_RRD:fail2ban" . $n . "_j2:AVERAGE", + "DEF:j3=$FAIL2BAN_RRD:fail2ban" . $n . "_j3:AVERAGE", + "DEF:j4=$FAIL2BAN_RRD:fail2ban" . $n . "_j4:AVERAGE", + "DEF:j5=$FAIL2BAN_RRD:fail2ban" . $n . "_j5:AVERAGE", + "DEF:j6=$FAIL2BAN_RRD:fail2ban" . $n . "_j6:AVERAGE", + "DEF:j7=$FAIL2BAN_RRD:fail2ban" . $n . "_j7:AVERAGE", + "DEF:j8=$FAIL2BAN_RRD:fail2ban" . $n . "_j8:AVERAGE", + "DEF:j9=$FAIL2BAN_RRD:fail2ban" . $n . "_j9:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNGz[$n]: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /fail2ban$n/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + if($title) { + print(" \n"); + } + $n++; + } + if($title) { + print(" \n"); + } + } + if($title) { + graph_footer(); + } + return 1; +} + +# ICECAST graph +# ---------------------------------------------------------------------------- +sub icecast { + my ($myself, $title) = @_; + + my $width; + my $height; + my @riglim; + my @PNG; + my @PNGz; + my @tmp; + my @tmpz; + my $e; + my $n; + my $str; + my $stack; + my $err; + my @AC = ( + "#FFA500", + "#44EEEE", + "#44EE44", + "#4444EE", + "#448844", + "#EE4444", + "#EE44EE", + "#EEEE44", + "#444444", + ); + my @LC = ( + "#FFA500", + "#00EEEE", + "#00EE00", + "#0000EE", + "#448844", + "#EE0000", + "#EE00EE", + "#EEEE00", + "#444444", + ); + + $title = !$silent ? $title : ""; + + if($IFACE_MODE eq "text") { + my $line1; + my $line2; + my $line3; + my $line4; + if($title) { + graph_header($title, 2); + print(" \n"); + print(" \n"); + } + my (undef, undef, undef, $data) = RRDs::fetch("$ICECAST_RRD", + "--start=-$nwhen$twhen", + "AVERAGE", + "-r $res"); + $err = RRDs::error; + print("ERROR: while fetching $ICECAST_RRD: $err\n") if $err; + print("
\n");
+		print("    ");
+		for($n = 0; $n < scalar(@ICECAST_URL_LIST); $n++) {
+			$line1 = "  ";
+			$line2 .= "  ";
+			$line3 .= "  ";
+			$line4 .= "--";
+			foreach my $i (@ICECAST_MP_LIST[$n]) {
+				foreach(@$i) {
+					$line1 .= "           ";
+					$line2 .= sprintf(" %10s", $_);
+					$line3 .= "  List BitR";
+					$line4 .= "-----------";
+				}
+			}
+			if($line1) {
+				$i = length($line1);
+				printf(sprintf("%${i}s", sprintf("Icecast Server %2d", $n)));
+			}
+		}
+		print("\n");
+		print("    $line2");
+		print("\n");
+		print("Time$line3\n");
+		print("----$line4 \n");
+		my $line;
+		my @row;
+		my $time;
+		my $n2;
+		my $n3;
+		my $from;
+		my $to;
+		for($n = 0, $time = $tb; $n < ($tb * $ts); $n++) {
+			$line = @$data[$n];
+			$time = $time - (1 / $ts);
+			printf(" %2d$tc", $time);
+			for($n2 = 0; $n2 < scalar(@ICECAST_URL_LIST); $n2++) {
+				print("  ");
+				foreach my $i (@ICECAST_MP_LIST[$n2]) {
+					for($n3 = 0; $n3 < scalar(@$i); $n3++) {
+						$from = $n2 * 36 + ($n3 * 4);
+						$to = $from + 4;
+						my ($l, $b, undef, undef) = @$line[$from..$to];
+						@row = ($l, $b);
+						printf("  %4d %4d", @row);
+					}
+				}
+			}
+			print("\n");
+		}
+		print("    
\n"); + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; + } + + for($n = 0; $n < scalar(@ICECAST_URL_LIST); $n++) { + $str = $u . $myself . $n . "1." . $when . ".png"; + push(@PNG, $str); + unlink("$PNG_DIR" . $str); + $str = $u . $myself . $n . "2." . $when . ".png"; + push(@PNG, $str); + unlink("$PNG_DIR" . $str); + if($ENABLE_ZOOM eq "Y") { + $str = $u . $myself . $n . "1z." . $when . ".png"; + push(@PNGz, $str); + unlink("$PNG_DIR" . $str); + $str = $u . $myself . $n . "2z." . $when . ".png"; + push(@PNGz, $str); + unlink("$PNG_DIR" . $str); + } + } + + $e = 0; + foreach my $url (@ICECAST_URL_LIST) { + if($e) { + print("
\n"); + } + if($title) { + graph_header($title, 2); + } + undef(@riglim); + if($ICECAST1_RIGID eq 1) { + push(@riglim, "--upper-limit=$ICECAST1_LIMIT"); + } else { + if($ICECAST1_RIGID eq 2) { + push(@riglim, "--upper-limit=$ICECAST1_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + foreach my $i (@ICECAST_MP_LIST[$e]) { + for($n = 0; $n < scalar(@$i); $n++) { + $str = sprintf("%-15s", substr(@$i[$n], 0, 15)); + if($ICECAST_GRAPH_MODE eq "S") { + $stack = ":STACK"; + } + push(@tmp, "AREA:ice" . $e . "_mp$n" . $AC[$n] . ":$str" . $stack); + push(@tmpz, "AREA:ice" . $e . "_mp$n" . $AC[$n] . ":@$i[$n]" . $stack); + push(@tmp, "GPRINT:ice" . $e . "_mp$n" . ":LAST: Cur\\:%4.0lf"); + push(@tmp, "GPRINT:ice" . $e . "_mp$n" . ":AVERAGE: Avg\\:%4.0lf"); + push(@tmp, "GPRINT:ice" . $e . "_mp$n" . ":MIN: Min\\:%4.0lf"); + push(@tmp, "GPRINT:ice" . $e . "_mp$n" . ":MAX: Max\\:%4.0lf\\n"); + } + } + if($ICECAST_GRAPH_MODE ne "S") { + foreach my $i (@ICECAST_MP_LIST[$e]) { + for($n = 0; $n < scalar(@$i); $n++) { + push(@tmp, "LINE1:ice" . $e . "_mp$n" . $LC[$n]); + push(@tmpz, "LINE2:ice" . $e . "_mp$n" . $LC[$n]); + } + } + } + + if($title) { + print(" \n"); + print(" \n"); + } + ($width, $height) = split('x', $GRAPH_SIZE{medium}); + RRDs::graph("$PNG_DIR" . "$PNG[$e * 2]", + "--title=$rgraphs{_icecast1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Listeners", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:ice" . $e . "_mp0=$ICECAST_RRD:icecast" . $e . "_mp0_ls:AVERAGE", + "DEF:ice" . $e . "_mp1=$ICECAST_RRD:icecast" . $e . "_mp1_ls:AVERAGE", + "DEF:ice" . $e . "_mp2=$ICECAST_RRD:icecast" . $e . "_mp2_ls:AVERAGE", + "DEF:ice" . $e . "_mp3=$ICECAST_RRD:icecast" . $e . "_mp3_ls:AVERAGE", + "DEF:ice" . $e . "_mp4=$ICECAST_RRD:icecast" . $e . "_mp4_ls:AVERAGE", + "DEF:ice" . $e . "_mp5=$ICECAST_RRD:icecast" . $e . "_mp5_ls:AVERAGE", + "DEF:ice" . $e . "_mp6=$ICECAST_RRD:icecast" . $e . "_mp6_ls:AVERAGE", + "DEF:ice" . $e . "_mp7=$ICECAST_RRD:icecast" . $e . "_mp7_ls:AVERAGE", + "DEF:ice" . $e . "_mp8=$ICECAST_RRD:icecast" . $e . "_mp8_ls:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG[$e * 2]: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNGz[$e * 2]", + "--title=$rgraphs{_icecast1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Listeners", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:ice" . $e . "_mp0=$ICECAST_RRD:icecast" . $e . "_mp0_ls:AVERAGE", + "DEF:ice" . $e . "_mp1=$ICECAST_RRD:icecast" . $e . "_mp1_ls:AVERAGE", + "DEF:ice" . $e . "_mp2=$ICECAST_RRD:icecast" . $e . "_mp2_ls:AVERAGE", + "DEF:ice" . $e . "_mp3=$ICECAST_RRD:icecast" . $e . "_mp3_ls:AVERAGE", + "DEF:ice" . $e . "_mp4=$ICECAST_RRD:icecast" . $e . "_mp4_ls:AVERAGE", + "DEF:ice" . $e . "_mp5=$ICECAST_RRD:icecast" . $e . "_mp5_ls:AVERAGE", + "DEF:ice" . $e . "_mp6=$ICECAST_RRD:icecast" . $e . "_mp6_ls:AVERAGE", + "DEF:ice" . $e . "_mp7=$ICECAST_RRD:icecast" . $e . "_mp7_ls:AVERAGE", + "DEF:ice" . $e . "_mp8=$ICECAST_RRD:icecast" . $e . "_mp8_ls:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNGz[$e * 2]: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /icecast$e/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + if($title) { + print(" \n"); + } + + undef(@riglim); + if($ICECAST2_RIGID eq 1) { + push(@riglim, "--upper-limit=$ICECAST2_LIMIT"); + } else { + if($ICECAST2_RIGID eq 2) { + push(@riglim, "--upper-limit=$ICECAST2_LIMIT"); + push(@riglim, "--rigid"); + } + } + undef(@tmp); + undef(@tmpz); + foreach my $i (@ICECAST_MP_LIST[$e]) { + for($n = 0; $n < scalar(@$i); $n++) { + $str = sprintf("%-15s", @$i[$n]); + push(@tmp, "LINE1:ice" . $e . "_mp$n" . $LC[$n] . ":$str"); + push(@tmpz, "LINE2:ice" . $e . "_mp$n" . $LC[$n] . ":@$i[$n]"); + push(@tmp, "GPRINT:ice" . $e . "_mp$n" . ":LAST: Cur\\:%3.0lf"); + push(@tmp, "GPRINT:ice" . $e . "_mp$n" . ":AVERAGE: Avg\\:%3.0lf"); + push(@tmp, "GPRINT:ice" . $e . "_mp$n" . ":MIN: Min\\:%3.0lf"); + push(@tmp, "GPRINT:ice" . $e . "_mp$n" . ":MAX: Max\\:%3.0lf\\n"); + } + } + + if($title) { + print(" \n"); + } + ($width, $height) = split('x', $GRAPH_SIZE{medium}); + RRDs::graph("$PNG_DIR" . $PNG[$e * 2 + 1], + "--title=$rgraphs{_icecast2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Bitrate", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:ice" . $e . "_mp0=$ICECAST_RRD:icecast" . $e . "_mp0_br:AVERAGE", + "DEF:ice" . $e . "_mp1=$ICECAST_RRD:icecast" . $e . "_mp0_br:AVERAGE", + "DEF:ice" . $e . "_mp2=$ICECAST_RRD:icecast" . $e . "_mp0_br:AVERAGE", + "DEF:ice" . $e . "_mp3=$ICECAST_RRD:icecast" . $e . "_mp0_br:AVERAGE", + "DEF:ice" . $e . "_mp4=$ICECAST_RRD:icecast" . $e . "_mp0_br:AVERAGE", + "DEF:ice" . $e . "_mp5=$ICECAST_RRD:icecast" . $e . "_mp0_br:AVERAGE", + "DEF:ice" . $e . "_mp6=$ICECAST_RRD:icecast" . $e . "_mp0_br:AVERAGE", + "DEF:ice" . $e . "_mp7=$ICECAST_RRD:icecast" . $e . "_mp0_br:AVERAGE", + "DEF:ice" . $e . "_mp8=$ICECAST_RRD:icecast" . $e . "_mp0_br:AVERAGE", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . $PNG[$e * 2 + 1] . ": $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . $PNGz[$e * 2 + 1], + "--title=$rgraphs{_icecast2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Bitrate", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:ice" . $e . "_mp0=$ICECAST_RRD:icecast" . $e . "_mp0_br:AVERAGE", + "DEF:ice" . $e . "_mp1=$ICECAST_RRD:icecast" . $e . "_mp0_br:AVERAGE", + "DEF:ice" . $e . "_mp2=$ICECAST_RRD:icecast" . $e . "_mp0_br:AVERAGE", + "DEF:ice" . $e . "_mp3=$ICECAST_RRD:icecast" . $e . "_mp0_br:AVERAGE", + "DEF:ice" . $e . "_mp4=$ICECAST_RRD:icecast" . $e . "_mp0_br:AVERAGE", + "DEF:ice" . $e . "_mp5=$ICECAST_RRD:icecast" . $e . "_mp0_br:AVERAGE", + "DEF:ice" . $e . "_mp6=$ICECAST_RRD:icecast" . $e . "_mp0_br:AVERAGE", + "DEF:ice" . $e . "_mp7=$ICECAST_RRD:icecast" . $e . "_mp0_br:AVERAGE", + "DEF:ice" . $e . "_mp8=$ICECAST_RRD:icecast" . $e . "_mp0_br:AVERAGE", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . $PNGz[$e * 2 + 1] . ": $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /icecast$e/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + if($title) { + print(" \n"); + print(" \n"); + + print(" \n"); + print " \n"; + print " \n"; + print " \n"; + print "   $url\n"; + print " \n"; + print " \n"; + print(" \n"); + graph_footer(); + } + $e++; + } + return 1; +} + +# INT graph +# ---------------------------------------------------------------------------- +sub int { + my ($myself, $title) = @_; + + my $width; + my $height; + my @riglim; + my $n; + my $err; + + my @INT; + my @NAME; + my @DEF1; + my @AREA1; + my @LINE1; + my @DEF2; + my @AREA2; + my @LINE2; + my @DEF3; + my @AREA3; + my @LINE3; + my $n1; + my $n2; + my $n3; + my @ACOLOR1 = ("#FFA500", + "#44EEEE", + "#CCCCCC", + "#B4B444", + "#4444EE", + "#44EE44", + "#EEEE44", + "#444444", + "#EE44EE", + "#EE4444", + "#448844", + "#BB44EE", + "#D3D701", + "#E29136", + "#DDAE8C", + "#F29967", + "#996952", + "#EB6C75", + "#B84F6B", + "#963C74", + "#A68BBC", + "#597AB7", + "#8CB4CE", + "#63BEE0", + "#3CB5B0", + "#7EB97C", + "#94C36B", + "#884632", + + "#CD5C5C", + "#F08080", + "#FA8072", + "#E9967A", + "#FFA07A", + "#DC143C", + "#B22222", + "#8B0000", + "#FFC0CB", + "#FF69B4", + "#FF1493", + "#C71585", + "#DB7093", + "#FFA07A", + "#FF7F50", + "#FF6347", + "#FF4500", + "#FF8C00", + "#FFD700", + "#FFFFE0", + "#FFFACD", + "#FFEFD5", + "#FFE4B5", + "#FFDAB9", + "#EEE8AA", + "#F0E68C", + "#BDB76B", + "#E6E6FA", + "#D8BFD8", + "#DDA0DD", + "#EE82EE", + "#DA70D6", + "#BA55D3", + "#9370DB", + "#9966CC", + "#8A2BE2", + "#9400D3", + "#9932CC", + "#8B008B", + "#4B0082", + "#6A5ACD", + "#483D8B", + "#7B68EE", + "#ADFF2F", + "#7FFF00", + "#32CD32", + "#98FB98", + "#90EE90", + "#00FA9A", + "#00FF7F", + "#3CB371", + "#2E8B57", + "#228B22", + "#9ACD32", + "#6B8E23", + "#808000", + "#556B2F", + "#66CDAA", + "#8FBC8F", + "#20B2AA", + "#008B8B", + "#007070", + "#E0FFFF", + "#AFEEEE", + "#7FFFD4", + "#40E0D0", + "#48D1CC", + "#00CED1", + "#5F9EA0", + "#4682B4", + "#B0C4DE", + "#B0E0E6", + "#ADD8E6", + "#87CEEB", + "#00BFFF", + "#1E90FF", + "#6495ED", + "#7B68EE", + "#4169E1", + "#191970", + "#FFF8DC", + "#FFEBCD", + "#FFDEAD", + "#F5DEB3", + "#DEB887", + "#D2B48C", + "#BC8F8F", + "#F4A460", + "#DAA520", + "#B8860B", + "#CD853F", + "#D2691E", + "#8B4513", + "#A0522D", + "#A52A2A", + "#800000", + "#FFFAFA", + "#F0FFF0", + "#F0F8FF", + "#F5F5F5", + "#FDF5E6", + "#F5F5DC", + "#FAEBD7", + "#FFE4E1", + "#DCDCDC", + "#696969", + "#A9A9A9", + "#708090", + "#2F4F4F", + "#000066", + "#006633", + "#660033", + "#66FFCC", + "#990066", + "#996633", + "#99CCCC", + "#CC3366", + "#CC6633", + "#CC6699", + "#CC9933", + "#CC9999", + "#CCCC33", + "#CCCC99", + "#CCFF99", + "#FF0099", + "#FF6666", + "#FF9999", + "#FFCC99", + "#FFFF99"); + + my @LCOLOR1 = ("#DDA500", + "#00EEEE", + "#888888", + "#B4B400", + "#0000EE", + "#00EE00", + "#EEEE00", + "#444444", + "#EE00EE", + "#EE0000", + "#008800", + "#BB00EE", + "#C8D200", + "#DB6612", + "#CE8248", + "#EB6A39", + "#8F4C30", + "#E20045", + "#B50C51", + "#7B0059", + "#684894", + "#125AA3", + "#518FBA", + "#00AADA", + "#009790", + "#359B52", + "#56AB27", + "#782F1E", + + "#CD5C5C", + "#F08080", + "#FA8072", + "#E9967A", + "#FFA07A", + "#DC143C", + "#B22222", + "#8B0000", + "#FFC0CB", + "#FF69B4", + "#FF1493", + "#C71585", + "#DB7093", + "#FFA07A", + "#FF7F50", + "#FF6347", + "#FF4500", + "#FF8C00", + "#FFD700", + "#FFFFE0", + "#FFFACD", + "#FFEFD5", + "#FFE4B5", + "#FFDAB9", + "#EEE8AA", + "#F0E68C", + "#BDB76B", + "#E6E6FA", + "#D8BFD8", + "#DDA0DD", + "#EE82EE", + "#DA70D6", + "#BA55D3", + "#9370DB", + "#9966CC", + "#8A2BE2", + "#9400D3", + "#9932CC", + "#8B008B", + "#4B0082", + "#6A5ACD", + "#483D8B", + "#7B68EE", + "#ADFF2F", + "#7FFF00", + "#32CD32", + "#98FB98", + "#90EE90", + "#00FA9A", + "#00FF7F", + "#3CB371", + "#2E8B57", + "#228B22", + "#9ACD32", + "#6B8E23", + "#808000", + "#556B2F", + "#66CDAA", + "#8FBC8F", + "#20B2AA", + "#008B8B", + "#007070", + "#E0FFFF", + "#AFEEEE", + "#7FFFD4", + "#40E0D0", + "#48D1CC", + "#00CED1", + "#5F9EA0", + "#4682B4", + "#B0C4DE", + "#B0E0E6", + "#ADD8E6", + "#87CEEB", + "#00BFFF", + "#1E90FF", + "#6495ED", + "#7B68EE", + "#4169E1", + "#191970", + "#FFF8DC", + "#FFEBCD", + "#FFDEAD", + "#F5DEB3", + "#DEB887", + "#D2B48C", + "#BC8F8F", + "#F4A460", + "#DAA520", + "#B8860B", + "#CD853F", + "#D2691E", + "#8B4513", + "#A0522D", + "#A52A2A", + "#800000", + "#FFFAFA", + "#F0FFF0", + "#F0F8FF", + "#F5F5F5", + "#FDF5E6", + "#F5F5DC", + "#FAEBD7", + "#FFE4E1", + "#DCDCDC", + "#696969", + "#A9A9A9", + "#708090", + "#2F4F4F", + "#000066", + "#006633", + "#660033", + "#66FFCC", + "#990066", + "#996633", + "#99CCCC", + "#CC3366", + "#CC6633", + "#CC6699", + "#CC9933", + "#CC9999", + "#CCCC33", + "#CCCC99", + "#CCFF99", + "#FF0099", + "#FF6666", + "#FF9999", + "#FFCC99", + "#FFFF99"); + + my @ACOLOR2 = ("#44EEEE", + "#4444EE", + "#44EE44", + "#EE44EE", + "#EE4444", + "#EEEE44"); + my @LCOLOR2 = ("#00EEEE", + "#0000EE", + "#00EE00", + "#EE00EE", + "#EE0000", + "#EEEE00"); + + my @ACOLOR3 = ("#44EE44", + "#4444EE", + "#44EEEE", + "#EE4444", + "#EE44EE", + "#EEEE44"); + my @LCOLOR3 = ("#00EE00", + "#0000EE", + "#00EEEE", + "#EE0000", + "#EE00EE", + "#EEEE00"); + + my $PNG1 = $u . $myself . "1." . $when . ".png"; + my $PNG2 = $u . $myself . "2." . $when . ".png"; + my $PNG3 = $u . $myself . "3." . $when . ".png"; + my $PNG1z = $u . $myself . "1z." . $when . ".png"; + my $PNG2z = $u . $myself . "2z." . $when . ".png"; + my $PNG3z = $u . $myself . "3z." . $when . ".png"; + + $title = !$silent ? $title : ""; + + unlink ("$PNG_DIR" . "$PNG1", + "$PNG_DIR" . "$PNG2", + "$PNG_DIR" . "$PNG3"); + if($ENABLE_ZOOM eq "Y") { + unlink ("$PNG_DIR" . "$PNG1z", + "$PNG_DIR" . "$PNG2z", + "$PNG_DIR" . "$PNG3z"); + } + + if($os eq "Linux") { + open(IN, "/proc/interrupts"); + my $timer_pos = 0; + my $i8042_pos = 0; + my $good_pos = 0; + my $num; + my $name; + while() { + if(/Dynamic-irq/) { + next; + } + if(/[0-9]:/) { + # Assuming int 0 will be only for timer + if(/\s+0:/ || /^256:/) { + $timer_pos = index($_, "timer", 0); + } + # Assuming int 1 will be only for i8042 + if(/\s+1:/) { + $i8042_pos = index($_, "i8042", 0); + } + $timer_pos = $timer_pos == 0 ? 999 : $timer_pos; + $i8042_pos = $i8042_pos == -1 ? 0 : $i8042_pos; + $good_pos = $timer_pos > $i8042_pos ? $i8042_pos : $timer_pos; + $good_pos = $good_pos ? $good_pos : $timer_pos; + $num = unpack("A4", $_); + undef($name); + if(length($_) >= $good_pos) { + $name = substr($_, $good_pos); + $name = defined($name) ? $name : ""; + } + chomp($num, $name); + $name =~ s/^\s+//; + $num =~ s/^\s+//; + $num =~ s/:.*//; + $n = $num; + $num = $num > 255 ? $num % 256 : $num; + $INT[$num] = defined($INT[$num]) ? $INT[$num] . "," : ""; + $NAME[$num] = defined($NAME[$num]) ? $NAME[$num] . ", " : ""; + $INT[$num] .= $n; + $NAME[$num] .= $name; + } + } + close(IN); + } elsif ($os eq "FreeBSD" || $os eq "OpenBSD") { + open(IN, "vmstat -i | sort |"); + my @allfields; + my $num; + my $name; + while() { + if(/^\D{3}\d+/) { + @allfields = split(' ', $_); + $num = $allfields[0]; + $name = ""; + for($n = 1; $n <= $#allfields - 2; $n++) { + $name .= $allfields[$n] . " "; + } + $num =~ s/^\D{3}//; + $num =~ s/://; + $name =~ s/\s+$//; + + # only the first timer (cpu0) is covered + if($name eq "timer") { + if($num != 0) { + next; + } + } + + $n = $num; + $num = $num > 255 ? $num % 256 : $num; + $INT[$num] = defined($INT[$num]) ? $INT[$num] . "," : ""; + $NAME[$num] = defined($NAME[$num]) ? $NAME[$num] . ", " : ""; + $INT[$num] .= $n; + $NAME[$num] .= $name; + } + } + close(IN); + + chomp(@NAME); + # strip all blank spaces at the end of the strings + for($n = 0; $n < 256; $n++) { + if(defined($NAME[$n])) { + $NAME[$n] =~ s/\s+$//; + } + } + } + + if($IFACE_MODE eq "text") { + if($title) { + graph_header($title, 2); + print(" \n"); + print(" \n"); + } + my (undef, undef, undef, $data) = RRDs::fetch("$INT_RRD", + "--start=-$nwhen$twhen", + "AVERAGE", + "-r $res"); + $err = RRDs::error; + print("ERROR: while fetching $INT_RRD: $err\n") if $err; + my $line1; + print("
\n");
+		print("Time   ");
+		for($n = 0; $n < 256; $n++) {
+			if(defined($INT[$n])) {
+				printf(" %8s", $INT[$n]);
+				$line1 .= "---------";
+			}
+		}
+		print(" \n");
+		print("-------$line1\n");
+		my $line;
+		my @row;
+		my $time;
+		for($n = 0, $time = $tb; $n < ($tb * $ts); $n++) {
+			$line = @$data[$n];
+			@row = @$line;
+			$time = $time - (1 / $ts);
+			printf(" %2d$tc   ", $time);
+			for($n2 = 0; $n2 < 256; $n2++) {
+				if(defined($INT[$n2])) {
+					printf(" %8d", $row[$n2]);
+				}
+			}
+			print(" \n");
+		}
+		print("    
\n"); + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; + } + + if($title) { + graph_header($title, 2); + } + + my $i; + for($n = 0, $n1 = 0, $n2 = 0, $n3 = 0; $n < 256; $n++) { + if(defined($NAME[$n])) { + # We need to escape colons to support RRDtool v1.2+ + if($RRDs::VERSION > 1.2) { + $NAME[$n] =~ s/:/\\:/g; + } + } + if(defined($INT[$n])) { + if(index($INT[$n], ",", 0) < 0) { + $i = $INT[$n]; + } else { + ($i) = split(',', $INT[$n]); + } + if($i < 3 || $NAME[$n] =~ /timer/) { + push(@DEF2, ("DEF:int" . $n . "=" . $INT_RRD . ":int_" . $n . ":AVERAGE")); + push(@AREA2, ("AREA:int" . $n . $ACOLOR2[$n2] . ":(" . $INT[$n] . ")" . $NAME[$n])); + push(@LINE2, ("LINE1:int" . $n . $LCOLOR2[$n2])); + $n2++; + } elsif($i < 6 || $NAME[$n] =~ /^xen/) { + push(@DEF3, ("DEF:int" . $n . "=" . $INT_RRD . ":int_" . $n . ":AVERAGE")); + push(@AREA3, ("AREA:int" . $n . $ACOLOR3[$n3] . ":(" . $INT[$n] . ")" . $NAME[$n])); + push(@LINE3, ("LINE1:int" . $n . $LCOLOR3[$n3])); + $n3++; + } else { + push(@DEF1, ("DEF:int" . $n . "=" . $INT_RRD . ":int_" . $n . ":AVERAGE")); + push(@AREA1, ("AREA:int" . $n . $ACOLOR1[$n1] . ":(" . $INT[$n] . ")" . $NAME[$n])); + push(@LINE1, ("LINE1:int" . $n . $LCOLOR1[$n1])); + $n1++; + if(!($n1 % 3)) { + push(@AREA1, ("COMMENT: \\n")); + } + } + } + } + push(@AREA1, ("COMMENT: \\n")); + if($INT1_RIGID eq 1) { + push(@riglim, "--upper-limit=$INT1_LIMIT"); + } else { + if($INT1_RIGID eq 2) { + push(@riglim, "--upper-limit=$INT1_LIMIT"); + push(@riglim, "--rigid"); + } + } + if($title) { + print(" \n"); + print(" \n"); + } + ($width, $height) = split('x', $GRAPH_SIZE{main}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + } + RRDs::graph("$PNG_DIR" . "$PNG1", + "--title=$rgraphs{_int1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Ticks/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + @DEF1, + @AREA1, + @LINE1); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG1: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG1z", + "--title=$rgraphs{_int1} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Ticks/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + @DEF1, + @AREA1, + @LINE1); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG1z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /int1/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + if($title) { + print(" \n"); + print(" \n"); + } + + undef(@riglim); + if($INT2_RIGID eq 1) { + push(@riglim, "--upper-limit=$INT2_LIMIT"); + } else { + if($INT2_RIGID eq 2) { + push(@riglim, "--upper-limit=$INT2_LIMIT"); + push(@riglim, "--rigid"); + } + } + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + } + RRDs::graph("$PNG_DIR" . "$PNG2", + "--title=$rgraphs{_int2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Ticks/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + @DEF2, + @AREA2, + @LINE2); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG2: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG2z", + "--title=$rgraphs{_int2} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Ticks/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + @DEF2, + @AREA2, + @LINE2); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG2z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /int2/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + + undef(@riglim); + if($INT3_RIGID eq 1) { + push(@riglim, "--upper-limit=$INT3_LIMIT"); + } else { + if($INT3_RIGID eq 2) { + push(@riglim, "--upper-limit=$INT3_LIMIT"); + push(@riglim, "--rigid"); + } + } + ($width, $height) = split('x', $GRAPH_SIZE{small}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $GRAPH_SIZE{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $GRAPH_SIZE{main}) if $silent eq "imagetagbig"; + } + if(@DEF3 && @AREA3 && @LINE3) { + RRDs::graph("$PNG_DIR" . "$PNG3", + "--title=$rgraphs{_int3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Ticks/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + @DEF3, + @AREA3, + @LINE3); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG3: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNG3z", + "--title=$rgraphs{_int3} ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=Ticks/s", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + @DEF3, + @AREA3, + @LINE3); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG3z: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /int3/)) { + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + } + } + if($title) { + print(" \n"); + print(" \n"); + graph_footer(); + } + return 1; +} + +# Multihost +# ---------------------------------------------------------------------------- +sub multihost { + my $n; + my $n2; + my $m; + my $m2; + my $gnum; + my @HOST; + my @URL; + my @TEMP_LIST; + + if($val eq "all") { + for($n = 0; $n < scalar(@REMOTEHOST_LIST); $n += 2) { + push(@HOST, $REMOTEHOST_LIST[$n]); + push(@URL, $REMOTEHOST_LIST[$n + 1]); + } + } else { + $gnum = substr($val, 5, length($val)); + @TEMP_LIST = split(':', $REMOTEGROUP_LIST[2 * $gnum + 1]); + $gnum = scalar(@TEMP_LIST); + $gnum = scalar(@REMOTEHOST_LIST); + for($m = 0; $m < scalar(@TEMP_LIST); $m += 1) { + for($m2 = 0; $m2 < scalar(@REMOTEHOST_LIST); $m2 += 2) { + if($TEMP_LIST[$m] eq $REMOTEHOST_LIST[$m2]) { + push(@HOST, $REMOTEHOST_LIST[$m2]); + push(@URL, $REMOTEHOST_LIST[$m2 + 1]); + } + } + } + } + + $MULTIHOST_IMGS_PER_ROW = 1 unless $MULTIHOST_IMGS_PER_ROW > 1; + $graph = ($graph eq "all" || $graph =~ m/group\[0-9]*/) ? "_system1" : $graph; + + if($val eq "all" || $val =~ m/group[0-9]*/) { + for($n = 0; $n < scalar(@HOST); $n += $MULTIHOST_IMGS_PER_ROW) { + print "\n"; + print " \n"; + for($n2 = 0; $n2 < $MULTIHOST_IMGS_PER_ROW; $n2++) { + if($n < scalar(@HOST)) { + print " \n"; + } + $n++; + } + print " \n"; + print " \n"; + for($n2 = 0, $n = $n - $MULTIHOST_IMGS_PER_ROW; $n2 < $MULTIHOST_IMGS_PER_ROW; $n2++) { + if($n < scalar(@HOST)) { + print " \n"; + + } + $n++; + } + print " \n"; + print " \n"; + for($n2 = 0, $n = $n - $MULTIHOST_IMGS_PER_ROW; $n2 < $MULTIHOST_IMGS_PER_ROW; $n2++) { + if($n < scalar(@HOST)) { + if($MULTIHOST_FOOTER) { + print " \n"; + } + } + $n++; + } + $n = $n - $MULTIHOST_IMGS_PER_ROW; + print " \n"; + print "
\n"; + print " \n"; + print "   " . $HOST[$n] . "\n"; + print " \n"; + print "
\n"; + print " \n"; + print "
\n"; + print " \n"; + print " \n"; + print "   $URL[$n]\n"; + print " \n"; + print "
\n"; + print "
\n"; + } + } else { + print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + if($MULTIHOST_FOOTER) { + print " \n"; + } + print " \n"; + print "
\n"; + print " \n"; + print "   " . $HOST[$val] . "\n"; + print " \n"; + print "
\n"; + print " \n"; + print "
\n"; + print " \n"; + print " \n"; + print "   $URL[$val]\n"; + print " \n"; + print "
\n"; + print "
\n"; + } +} + +sub pc { + my $width; + my $height; + my @riglim; + my @PNG; + my @PNGz; + my @tmp; + my @tmpz; + my @CDEF; + my $T = "B"; + my $vlabel = "bytes/s"; + my $n; + my $n2; + my $str; + my $err; + + for($n = 0; $n < $PC_MAX; $n++) { + $str = $u . "pc" . $n . ".$when" . ".png"; + push(@PNG, $str); + unlink("$PNG_DIR" . $str); + if($ENABLE_ZOOM eq "Y") { + $str = $u . "pc" . $n . "z.$when" . ".png"; + push(@PNGz, $str); + unlink("$PNG_DIR" . $str); + } + } + if($PC_RIGID eq 1) { + $riglim[0] = "--upper-limit=$PC_LIMIT"; + } else { + if($PC_RIGID eq 2) { + $riglim[0] = "--upper-limit=$PC_LIMIT"; + $riglim[1] = "--rigid"; + } + } + + if($NETSTATS_IN_BPS eq "Y") { + $T = "b"; + $vlabel = "bits/s"; + } + $PC_IMGS_PER_ROW = 1 unless $PC_IMGS_PER_ROW > 1; + if($val eq "all") { + print(" \n"); + print(" \n"); + print(" \n"); + print(" \n"); + $n = 0; + while($n < $PC_MAX) { + last unless $PC_LIST[$n]; + print(" \n"); + for($n2 = 0; $n2 < $PC_IMGS_PER_ROW; $n2++) { + last unless ($n < $PC_MAX && $n < scalar(@PC_LIST)); + print(" \n"); + $n++; + } + print(" \n"); + } + print "
\n"); + print(" \n"); + print("   Internet traffic and usage\n"); + print(" \n"); + print("
\n"); + undef(@tmp); + undef(@tmpz); + undef(@CDEF); + push(@tmp, "AREA:B_in#44EE44:Input"); + push(@tmp, "AREA:B_out#4444EE:Output"); + push(@tmp, "AREA:B_out#4444EE:"); + push(@tmp, "AREA:B_in#44EE44:"); + push(@tmp, "LINE1:B_out#0000EE"); + push(@tmp, "LINE1:B_in#00EE00"); + push(@tmpz, "AREA:B_in#44EE44:Input"); + push(@tmpz, "AREA:B_out#4444EE:Output"); + push(@tmpz, "AREA:B_out#4444EE:"); + push(@tmpz, "AREA:B_in#44EE44:"); + push(@tmpz, "LINE1:B_out#0000EE"); + push(@tmpz, "LINE1:B_in#00EE00"); + if($NETSTATS_IN_BPS eq "Y") { + push(@CDEF, "CDEF:B_in=in,8,*"); + push(@CDEF, "CDEF:B_out=out,8,*"); + } else { + push(@CDEF, "CDEF:B_in=in"); + push(@CDEF, "CDEF:B_out=out"); + } + ($width, $height) = split('x', $GRAPH_SIZE{remote}); + RRDs::graph("$PNG_DIR" . "$PNG[$n]", + "--title=$PC_LIST[$n] traffic ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=$vlabel", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:in=$PC_RRD:pc" . $n . "_in:AVERAGE", + "DEF:out=$PC_RRD:pc" . $n . "_out:AVERAGE", + @CDEF, + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG[$n]: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNGz[$n]", + "--title=$PC_LIST[$n] traffic ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=$vlabel", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @VERSION12_small, + @graph_colors, + "DEF:in=$PC_RRD:pc" . $n . "_in:AVERAGE", + "DEF:out=$PC_RRD:pc" . $n . "_out:AVERAGE", + @CDEF, + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNGz[$n]: $err\n") if $err; + } + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + print("
\n"; + } else { + return unless $PC_LIST[$val]; + if(!$silent) { + print(" \n"); + print(" \n"); + print(" \n"); + print(" \n"); + print(" \n"); + print(" \n"); + print " \n"; + print " \n"; + print "
\n"); + print(" \n"); + print("   Internet traffic and usage\n"); + print(" \n"); + print("
\n"); + } + undef(@tmp); + undef(@tmpz); + undef(@CDEF); + push(@tmp, "AREA:B_in#44EE44:K$T/s Input"); + push(@tmp, "GPRINT:K_in:LAST: Current\\: %5.0lf"); + push(@tmp, "GPRINT:K_in:AVERAGE: Average\\: %5.0lf"); + push(@tmp, "GPRINT:K_in:MIN: Min\\: %5.0lf"); + push(@tmp, "GPRINT:K_in:MAX: Max\\: %5.0lf\\n"); + push(@tmp, "AREA:B_out#4444EE:K$T/s Output"); + push(@tmp, "GPRINT:K_out:LAST: Current\\: %5.0lf"); + push(@tmp, "GPRINT:K_out:AVERAGE: Average\\: %5.0lf"); + push(@tmp, "GPRINT:K_out:MIN: Min\\: %5.0lf"); + push(@tmp, "GPRINT:K_out:MAX: Max\\: %5.0lf\\n"); + push(@tmp, "AREA:B_out#4444EE:"); + push(@tmp, "AREA:B_in#44EE44:"); + push(@tmp, "LINE1:B_out#0000EE"); + push(@tmp, "LINE1:B_in#00EE00"); + push(@tmpz, "AREA:B_in#44EE44:Input"); + push(@tmpz, "AREA:B_out#4444EE:Output"); + push(@tmpz, "AREA:B_out#4444EE:"); + push(@tmpz, "AREA:B_in#44EE44:"); + push(@tmpz, "LINE1:B_out#0000EE"); + push(@tmpz, "LINE1:B_in#00EE00"); + if($NETSTATS_IN_BPS eq "Y") { + push(@CDEF, "CDEF:B_in=in,8,*"); + push(@CDEF, "CDEF:B_out=out,8,*"); + } else { + push(@CDEF, "CDEF:B_in=in"); + push(@CDEF, "CDEF:B_out=out"); + } + ($width, $height) = split('x', $GRAPH_SIZE{main}); + RRDs::graph("$PNG_DIR" . "$PNG[$val]", + "--title=$PC_LIST[$val] traffic ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=$vlabel", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:in=$PC_RRD:pc" . $val . "_in:AVERAGE", + "DEF:out=$PC_RRD:pc" . $val . "_out:AVERAGE", + @CDEF, + "CDEF:K_in=B_in,1024,/", + "CDEF:K_out=B_out,1024,/", + @tmp); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNG[$val]: $err\n") if $err; + if($ENABLE_ZOOM eq "Y") { + ($width, $height) = split('x', $GRAPH_SIZE{zoom}); + RRDs::graph("$PNG_DIR" . "$PNGz[$val]", + "--title=$PC_LIST[$val] traffic ($nwhen$twhen)", + "--start=-$nwhen$twhen", + "--imgformat=PNG", + "--vertical-label=$vlabel", + "--width=$width", + "--height=$height", + @riglim, + "--lower-limit=0", + @VERSION12, + @graph_colors, + "DEF:in=$PC_RRD:pc" . $val . "_in:AVERAGE", + "DEF:out=$PC_RRD:pc" . $val . "_out:AVERAGE", + @CDEF, + "CDEF:K_in=B_in,1024,/", + "CDEF:K_out=B_out,1024,/", + @tmpz); + $err = RRDs::error; + print("ERROR: while graphing $PNG_DIR" . "$PNGz[$val]: $err\n") if $err; + } + if($ENABLE_ZOOM eq "Y") { + if($DISABLE_JAVASCRIPT_VOID eq "Y") { + print(" \n"); + } + else { + print(" \n"); + } + } else { + print(" \n"); + } + if(!$silent) { + print("
\n"; + } + } +} + +sub graph_header { + my ($title, $colspan) = @_; + print("\n"); + print(" \n"); + print(" \n"); + print(" \n"); + print(" \n"); +} + +sub graph_footer { + print("
\n"); + print(" \n"); + print("   $title\n"); + print(" \n"); + print("
\n"); +} + + +# MAIN +# ---------------------------------------------------------------------------- +print("Content-Type: text/html\n"); +print("\n"); +if(!$silent) { + my $title; + my $str; + + print("\n"); + print(" \n"); + print(" $TITLE\n"); + print(" \n"); + if($REFRESH_RATE) { + print(" \n"); + } + print(" \n"); + print(" \n"); + print("
\n"); + print(" \n"); + print(" \n"); + if(($val ne "all" || $val ne "group") && $mode ne "multihost") { + print(" \n"); + } + if($val =~ m/group[0-9]+/) { + my $gnum = substr($val, 5, length($val)); + my $gname = $REMOTEGROUP_LIST[2 * $gnum]; + print(" \n"); + } + print(" \n"); + print(" \n"); + print(" \n"); + print("
\n"); + print(" \n"); + print("   Host: \n"); + print(" \n"); + print(" \n"); + print(" \n"); + print("   $gname \n"); + print(" \n"); + print(" \n"); + print(" \n"); + if($mode eq "localhost" || $mode eq "pc") { + $title = $HOSTNAME; + } elsif($mode eq "multihost") { + $graph = $graph eq "all" ? "_system1" : $graph; + if(substr($graph, 0, 4) eq "_net") { + $str = "_net" . substr($graph, 5, 1); + $title = $rgraphs{$str}; + } elsif(substr($graph, 0, 5) eq "_port") { + $str = substr($graph, 0, 5); + $n = substr($graph, 5, 1); + $title = $rgraphs{$str}; + $title .= " " . $PORT_LIST[$n]; + $title .= " (" . $PORT_NAME[$n] . ")"; + } else { + $title = $rgraphs{$graph}; + } + } + $title =~ s/ / /g; + print("   $title  \n"); + print(" \n"); + print(" \n"); + print(" \n"); + print("   last $twhen  \n"); + print(" \n"); + print("
\n"); + print(" \n"); + print("

" . strftime("%a %b %e %H:%M:%S %Z %Y", localtime) . "

\n"); +} + +if($mode eq "localhost") { + foreach my $g (@GRAPH_NAME) { + if($GRAPH_ENABLE{$g} eq "Y") { + if($graph eq "all" || $graph =~ /_$g/) { + if(eval {&$g($g, $GRAPH_TITLE{$g});}) { + print("
\n"); + } + } + } + } +} elsif($mode eq "multihost") { + multihost(); +} elsif($mode eq "pc") { + pc(); +} + +if(!$silent) { + print("\n"); + print("
\n"); + print("
\n"); + print("

\n"); + print(" \n"); + print("
\n"); + print(" \n"); + print("Copyright © 2005-2012 Jordi Sanfeliu\n"); + print(" \n"); + print(" \n"); + print("\n"); +} + +exit(0); diff --git a/monitorix.conf b/monitorix.conf new file mode 100644 index 0000000..09f1eb8 --- /dev/null +++ b/monitorix.conf @@ -0,0 +1,1022 @@ +#!/usr/bin/perl +# +# Monitorix - configuration file +# Copyright (C) 2005-2012 by Jordi Sanfeliu +# +# Please be careful when touching this file taking special attention to +# not break some Perl basic syntax. +# +# See monitorix.conf(5) manpage for a detailed information of each option. +# + +use strict; + +our $TITLE = "Place a Title Here"; +our $HOSTNAME = ""; +our $THEME_COLOR = "black"; +our $REFRESH_RATE = "150"; +our $IFACE_MODE = "graph"; +our $ENABLE_ZOOM = "Y"; +our $NETSTATS_IN_BPS = "N"; +our $DISABLE_JAVASCRIPT_VOID = "N"; + +our $BASE_DIR = "/usr/share/monitorix/"; +our $BASE_LIB = "/var/lib/monitorix/"; +our $BASE_URL = "/monitorix"; +our $BASE_CGI = "/monitorix-cgi"; + + +# Log files pathnames +# ----------------------------------------------------------------------------- +our $LOG_FILE = "/var/log/monitorix"; +our $SECURE_LOG = "/var/log/secure"; +our $MAIL_LOG = "/var/log/maillog"; +our $MILTER_GL = "/var/milter-greylist/greylist.db"; +our $IMAP_LOG = "/var/log/imap"; +our $HYLAFAX_LOG = "/var/spool/hylafax/etc/xferfaxlog"; +our $CUPS_LOG = "/var/log/cups/page_log"; +our $FAIL2BAN_LOG = "/var/log/fail2ban.log"; +our $SPAMASSASSIN_LOG = "/var/log/maillog"; +our $CLAMAV_LOG = "/var/log/clamav/clamav.log"; +our $CG_LOGDIR = "/var/CommuniGate/SystemLogs/"; +our $SQUID_LOG = "/var/log/squid/access.log"; + +our $IMAP_DATE_LOG_FORMAT = "%b %d"; + + +# Alert capabilities +# ----------------------------------------------------------------------------- +our $ENABLE_ALERTS = "N"; +our $ALERT_LOADAVG_TIMEINTVL = "3600"; +our $ALERT_LOADAVG_THRESHOLD = "5.0"; +our $ALERT_LOADAVG_SCRIPT = "/path/to/script.sh"; + +our $ALERT_ROOTFS_TIMEINTVL = "3600"; +our $ALERT_ROOTFS_THRESHOLD = "100"; +our $ALERT_ROOTFS_SCRIPT = "/path/to/script.sh"; + + +# Graphs (de)activation +# ----------------------------------------------------------------------------- +our %GRAPH_ENABLE = ( + "system" => "Y", + "kern" => "Y", + "proc" => "Y", + "hptemp" => "N", + "lmsens" => "N", + "nvidia" => "N", + "disk" => "N", + "fs" => "Y", + "net" => "Y", + "serv" => "Y", + "mail" => "N", + "port" => "Y", + "user" => "Y", + "apache" => "N", + "nginx" => "N", + "lighttpd" => "N", + "mysql" => "N", + "squid" => "N", + "nfss" => "N", + "nfsc" => "N", + "bind" => "N", + "ntp" => "N", + "fail2ban" => "N", + "icecast" => "N", + "int" => "Y", +); + + +# SYSTEM graph +# ----------------------------------------------------------------------------- +our $SYSTEM1_RIGID = "1"; +our $SYSTEM1_LIMIT = "1"; +our $SYSTEM2_RIGID = "0"; +our $SYSTEM2_LIMIT = "100"; + + +# KERNEL graph +# ----------------------------------------------------------------------------- +our $KERN_GRAPH_MODE = "R"; +our $KERN1_RIGID = "2"; +our $KERN1_LIMIT = "100"; +our %KERN_DATA = ( + "user" => "Y", + "nice" => "Y", + "sys" => "Y", + "iow" => "Y", + "irq" => "Y", + "sirq" => "Y", + "steal" => "Y", + "guest" => "Y", +); + + +# PROC graph +# ----------------------------------------------------------------------------- +our $PROC_MAX = "4"; +our $PROC_PER_ROW = "2"; +our $PROC_SIZE = "medium"; +our $PROC_DATA = "Y"; +our $PROC_RIGID = "2"; +our $PROC_LIMIT = "100"; + + +# HPTEMP graph +# ----------------------------------------------------------------------------- +our @HPTEMP_1 = ( + "2", + "3", +); +our @HPTEMP_2 = ( + "1", + "6", +); +our @HPTEMP_3 = ( + "16", + "18", + "19", + "20", + "21", + "22", +); + + +# LMSENS graph +# ----------------------------------------------------------------------------- +our %SENSORS_LIST = ( + "CORE0" => "Core 0", + "CORE1" => "Core 1", + "MB0" => "M/B Temp", + "CPU0" => "CPU Temp", + "FAN0" => "fan1", + "FAN1" => "fan2", + "FAN2" => "fan3", + "VOLT0" => "VCore 1", + "VOLT1" => "VCore 2", + "VOLT2" => "\\+3.3V", + "VOLT3" => "\\+5V", + "VOLT4" => "\\+12V", + "VOLT5" => "\\-12V", + "VOLT6" => "\\-5V", + "VOLT7" => "Battery", + "GPU0" => "nvidia", +); + + +# NVIDIA graph +# ----------------------------------------------------------------------------- +our $NVIDIA_MAX = 1; + + +# DISK graph +# ----------------------------------------------------------------------------- +our @DISK_LIST = ( + [ + "/dev/sda", + "/dev/sdb", + "/dev/sdc", + ], +); + + +# FS graph +# ----------------------------------------------------------------------------- +our @FS_LIST = ( + [ + "/", + "swap", + "/boot", + ], +); +our %FS_DESC = ( +); +our %FS_DEV = ( +); +our $FS2_RIGID = "0"; +our $FS2_LIMIT = "1000"; +our $FS3_RIGID = "0"; +our $FS3_LIMIT = "1000"; + + +# NET graph +# ----------------------------------------------------------------------------- +our @NET_LIST = ( + "eth0", +); +our @NET_DESC = ( + "FastEthernet LAN", +); +our @NET_RIGID = ( + "0", +); +our @NET_LIMIT = ( + "10000000", +); +our $NET_GATEWAY = "eth0"; + + +# SERV graph +# ----------------------------------------------------------------------------- +our $SERV_MODE = "I"; +our $SERV1_RIGID = "0"; +our $SERV1_LIMIT = "1000"; +our $SERV2_RIGID = "0"; +our $SERV2_LIMIT = "1000"; +our $SERV3_RIGID = "0"; +our $SERV3_LIMIT = "1000"; + + +# MAIL graph +# ----------------------------------------------------------------------------- +our $MAIL_MTA = "sendmail"; +our $MAIL_GREYLIST = "milter-greylist"; +our $MAIL1_RIGID = "0"; +our $MAIL1_LIMIT = "1"; +our $MAIL2_RIGID = "0"; +our $MAIL2_LIMIT = "1000"; +our $MAIL3_RIGID = "0"; +our $MAIL3_LIMIT = "1000"; +our $MAIL4_RIGID = "0"; +our $MAIL4_LIMIT = "1000"; +our $MAIL5_RIGID = "0"; +our $MAIL5_LIMIT = "1000"; + + +# PORT graph +# ----------------------------------------------------------------------------- +our $PORT_MAX = "9"; +our $PORT_RULE = "24000"; +our @PORT_LIST = ( + "25", + "21", + "80", + "22", + "110", + "139", + "3306", + "53", + "143", +); +our @PORT_NAME = ( + "SMTP", + "FTP", + "HTTP", + "SSH", + "POP3", + "NETBIOS", + "MYSQL", + "DNS", + "IMAP", +); +our @PORT_PROT = ( + "tcp", + "tcp", + "tcp", + "tcp", + "tcp", + "tcp", + "tcp", + "udp", + "tcp", +); +our @PORT_RIGID = ( + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", +); +our @PORT_LIMIT = ( + "1000", + "1000", + "1000", + "1000", + "1000", + "1000", + "1000", + "1000", + "1000", +); + + +# USER graph +# ----------------------------------------------------------------------------- +our $USER1_RIGID = "0"; +our $USER1_LIMIT = "100"; +our $USER2_RIGID = "0"; +our $USER2_LIMIT = "100"; +our $USER3_RIGID = "0"; +our $USER3_LIMIT = "100"; + + +# APACHE graph +# ----------------------------------------------------------------------------- +our @APACHE_LIST = ( + "http://localhost/", +); +our $APACHE1_RIGID = "0"; +our $APACHE1_LIMIT = "100"; +our $APACHE2_RIGID = "2"; +our $APACHE2_LIMIT = "100"; +our $APACHE3_RIGID = "0"; +our $APACHE3_LIMIT = "100"; + + +# NGINX graph +# ----------------------------------------------------------------------------- +our $NGINX_PORT = "80"; +our $NGINX_RULE = "24100"; +our $NGINX1_RIGID = "0"; +our $NGINX1_LIMIT = "100"; +our $NGINX2_RIGID = "0"; +our $NGINX2_LIMIT = "100"; +our $NGINX3_RIGID = "0"; +our $NGINX3_LIMIT = "100"; + + +# LIGHTTPD graph +# ----------------------------------------------------------------------------- +our @LIGHTTPD_LIST = ( + "http://localhost/", +); +our $LIGHTTPD1_RIGID = "0"; +our $LIGHTTPD1_LIMIT = "100"; +our $LIGHTTPD2_RIGID = "0"; +our $LIGHTTPD2_LIMIT = "100"; +our $LIGHTTPD3_RIGID = "0"; +our $LIGHTTPD3_LIMIT = "100"; + + +# MYSQL graph +# ----------------------------------------------------------------------------- +our $MYSQL_CONN_TYPE = "Host"; +our @MYSQL_HOST_LIST = ( + "localhost", +); +our @MYSQL_PORT_LIST = ( + "3306", +); +our @MYSQL_USER_LIST = ( + "", +); +our @MYSQL_PASS_LIST = ( + "", +); +our @MYSQL_SOCK_LIST = ( + "/var/lib/mysql/mysql.sock", +); +our $MYSQL1_RIGID = "0"; +our $MYSQL1_LIMIT = "100"; +our $MYSQL2_RIGID = "2"; +our $MYSQL2_LIMIT = "100"; +our $MYSQL3_RIGID = "0"; +our $MYSQL3_LIMIT = "100"; +our $MYSQL4_RIGID = "0"; +our $MYSQL4_LIMIT = "100"; +our $MYSQL5_RIGID = "0"; +our $MYSQL5_LIMIT = "100"; +our $MYSQL6_RIGID = "0"; +our $MYSQL6_LIMIT = "100"; + + +# SQUID graph +# ----------------------------------------------------------------------------- +our $SQUID_CMD = "squidclient -h 127.0.0.1"; +our @SQUID_GRAPH_1 = ( + "TCP_MISS", + "TCP_DENIED", + "TCP_REFRESH_HIT", + "TCP_IMS_HIT", + "TCP_HIT", + "TCP_REFRESH_MISS", + "TCP_MEM_HIT", + "TCP_NEGATIVE_HIT", + "TCP_CLIENT_REFRESH_MISS", +); +our @SQUID_GRAPH_2 = ( + "200", + "403", + "304", + "204", + "302", + "000", + "404", + "301", + "206", +); +our $SQUID1_RIGID = "0"; +our $SQUID1_LIMIT = "100"; +our $SQUID2_RIGID = "0"; +our $SQUID2_LIMIT = "100"; +our $SQUID3_RIGID = "0"; +our $SQUID3_LIMIT = "100"; +our $SQUID4_RIGID = "0"; +our $SQUID4_LIMIT = "100"; +our $SQUID5_RIGID = "0"; +our $SQUID5_LIMIT = "100"; +our $SQUID6_RIGID = "0"; +our $SQUID6_LIMIT = "100"; +our $SQUID7_RIGID = "0"; +our $SQUID7_LIMIT = "100"; +our $SQUID8_RIGID = "0"; +our $SQUID8_LIMIT = "100"; +our $SQUID9_RIGID = "0"; +our $SQUID9_LIMIT = "100"; + + +# NFSS graph +# ----------------------------------------------------------------------------- +our $NFSS_VERSION = "3"; +our @NFSS_GRAPH_1 = ( + "readlink", + "create", + "mkdir", + "symlink", + "rmdir", + "remove", + "rename", + "link", + "readdir", +); +our @NFSS_GRAPH_2 = ( + "mknod", + "readdirplus", + "fsstat", + "fsinfo", + "pathconf", + "access", + "lookup", + "commit", + "null", +); +our @NFSS_GRAPH_3 = ( + "read", + "write", + "getattr", + "setattr", +); +our $NFSS1_RIGID = "0"; +our $NFSS1_LIMIT = "100"; +our $NFSS2_RIGID = "0"; +our $NFSS2_LIMIT = "100"; +our $NFSS3_RIGID = "0"; +our $NFSS3_LIMIT = "100"; +our $NFSS4_RIGID = "0"; +our $NFSS4_LIMIT = "100"; +our $NFSS5_RIGID = "0"; +our $NFSS5_LIMIT = "100"; +our $NFSS6_RIGID = "0"; +our $NFSS6_LIMIT = "100"; +our $NFSS7_RIGID = "0"; +our $NFSS7_LIMIT = "100"; +our $NFSS8_RIGID = "0"; +our $NFSS8_LIMIT = "100"; +our $NFSS9_RIGID = "0"; +our $NFSS9_LIMIT = "100"; + + +# NFSC graph +# ----------------------------------------------------------------------------- +our $NFSC_VERSION = "3"; +our @NFSC_GRAPH_1 = ( + "readlink", + "create", + "mkdir", + "symlink", + "rmdir", + "remove", + "rename", + "link", + "readdir", +); +our @NFSC_GRAPH_2 = ( + "mknod", + "readdirplus", + "fsstat", + "fsinfo", + "pathconf", +); +our @NFSC_GRAPH_3 = ( + "read", + "write", +); +our @NFSC_GRAPH_4 = ( + "getattr", + "setattr", +); +our @NFSC_GRAPH_5 = ( + "access", + "lookup", + "commit", + "null", +); +our $NFSC1_RIGID = "0"; +our $NFSC1_LIMIT = "100"; +our $NFSC2_RIGID = "0"; +our $NFSC2_LIMIT = "100"; +our $NFSC3_RIGID = "0"; +our $NFSC3_LIMIT = "100"; +our $NFSC4_RIGID = "0"; +our $NFSC4_LIMIT = "100"; +our $NFSC5_RIGID = "0"; +our $NFSC5_LIMIT = "100"; +our $NFSC6_RIGID = "0"; +our $NFSC6_LIMIT = "100"; + + +# BIND graph +# ----------------------------------------------------------------------------- +our @BIND_URL_LIST = ( + "http://localhost:8053/", +); +our @BIND_IN_QUERIES_LIST = ( + [ + "A", + "AAAA", + "ANY", + "DS", + "MX", + "NS", + "PTR", + "SOA", + "SRV", + "TXT", + "NAPTR", + "A6", + "CNAME", + "SPF", + "KEY", + "DNSKEY", + "HINFO", + "WKS", + "PX", + "NSAP", + ], +); +our @BIND_OUT_QUERIES_LIST = ( + [ + "A", + "AAAA", + "ANY", + "DS", + "MX", + "NS", + "PTR", + "SOA", + "SRV", + "TXT", + "NAPTR", + "A6", + "CNAME", + "SPF", + "KEY", + "DNSKEY", + "HINFO", + "WKS", + "PX", + "NSAP", + ], +); +our @BIND_SERVER_STATS_LIST = ( + [ + "Requestv4", + "Requestv6", + "ReqEdns0", + "ReqBadEDNSVer", + "ReqTSIG", + "ReqSIG0", + "ReqBadSIG", + "ReqTCP", + "Response", + "QrySuccess", + "QryAuthAns", + "QryNoauthAns", + "QryReferral", + "QryNxrrset", + "QrySERVFAIL", + "QryNXDOMAIN", + "QryRecursion", + "QryDuplicate", + "QryDropped", + "QryFailure", + ], +); +our @BIND_RESOLVER_STATS_LIST = ( + [ + "Queryv4", + "Queryv6", + "Responsev4", + "Responsev6", + "NXDOMAIN", + "SERVFAIL", + "FORMERR", + "OtherError", + "EDNS0Fail", + "Truncated", + "Lame", + "Retry", + "QueryTimeout", + "GlueFetchv4", + "GlueFetchv6", + "GlueFetchv4Fail", + "GlueFetchv6Fail", + "ValAttempt", + "ValOk", + "ValNegOk", + ], +); +our @BIND_CACHE_RRSETS_LIST = ( + [ + "A", + "!A", + "AAAA", + "!AAAA", + "DLV", + "!DLV", + "DS", + "!DS", + "MX", + "NS", + "CNAME", + "!CNAME", + "SOA", + "!SOA", + "!ANY", + "PTR", + "RRSIG", + "NSEC", + "DNSKEY", + "NXDOMAIN", + ], +); +our $BIND1_RIGID = "0"; +our $BIND1_LIMIT = "100"; +our $BIND2_RIGID = "0"; +our $BIND2_LIMIT = "100"; +our $BIND3_RIGID = "0"; +our $BIND3_LIMIT = "100"; +our $BIND4_RIGID = "0"; +our $BIND4_LIMIT = "100"; +our $BIND5_RIGID = "0"; +our $BIND5_LIMIT = "100"; + + +# NTP graph +# ----------------------------------------------------------------------------- +our @NTP_HOST_LIST = ( + "localhost", +); +our @NTP_CODE_LIST = ( + [ + "AUTH", + "AUTO", + "CRYP", + "DENY", + "GPS", + "INIT", + "NKEY", + "RATE", + "RMOT", + "RSTR", + ], +); +our $NTP1_RIGID = "0"; +our $NTP1_LIMIT = "100"; +our $NTP2_RIGID = "0"; +our $NTP2_LIMIT = "100"; + + +# FAIL2BAN graph +# ----------------------------------------------------------------------------- +our $FAIL2BAN_PER_ROW = "2"; +our @FAIL2BAN_LIST = ( + [ + "[apache]", + "[apache-mod-security]", + "[apache-overflows]", + "[courierauth]", + "[ssh]", + "[pam-generic]", + "[php-url-fopen]", + "[vsftpd]", + ], + [ + "[apache-imdbphp]", + "[apache-evasive]", + "[apache-badbots]", + "[apache-robots-txt]", + "[communigate]", + "[named-refused-udp]", + "[named-refused-tcp]", + "[trac-ticketspam]", + ], +); +our @FAIL2BAN_DESC = ( + "Security", + "Overload / Abuse", +); +our $FAIL2BAN_RIGID = "0"; +our $FAIL2BAN_LIMIT = "100"; + + +# ICECAST graph +# ----------------------------------------------------------------------------- +our @ICECAST_URL_LIST = ( + "http://localhost:8000/status.xsl", +); +our @ICECAST_MP_LIST = ( + [ + "stream1", + "stream2", + "stream3", + ], +); +our $ICECAST_GRAPH_MODE = "R"; +our $ICECAST1_RIGID = "0"; +our $ICECAST1_LIMIT = "100"; +our $ICECAST2_RIGID = "0"; +our $ICECAST2_LIMIT = "100"; + + +# INT graph +# ----------------------------------------------------------------------------- +our $INT1_RIGID = "0"; +our $INT1_LIMIT = "100"; +our $INT2_RIGID = "0"; +our $INT2_LIMIT = "100"; +our $INT3_RIGID = "0"; +our $INT3_LIMIT = "100"; + + +# Multihost +# ----------------------------------------------------------------------------- +our $MULTIHOST = "N"; +our $MULTIHOST_FOOTER = "Y"; +our $MULTIHOST_IMGS_PER_ROW = "2"; +our @REMOTEHOST_LIST = ( + "server 1", "http://www.example.com", + "server 2", "http://10.0.0.1", + "server 3", "http://192.168.0.100:8080", +); +our $GROUPS = "N"; +our @REMOTEGROUP_LIST = ( + "My Group", "server 2:server 3", +); + + +# PC LAN Internet traffic accounting +# ----------------------------------------------------------------------------- +our $PC_LAN = "N"; +our $PC_MAX = "10"; +our $PC_RIGID = "0"; +our $PC_LIMIT = "1000"; +our $PC_IMGS_PER_ROW = "2"; +our @PC_LIST = ( + "pc101", + "pc102", + "pc103", + "pc104", +); +our @PC_IP = ( + "192.168.1.101/32", + "192.168.1.102/32", + "192.168.1.103/32", + "192.168.1.104/32", +); +our $PC_ENABLE_MONTHLY_REPORTS = "N"; +our $PC_REPORT_LANG = "en"; +our $PC_DEFAULT_MAIL = "root\@localhost"; +our @PC_REPORT_MAIL = ( + "ace\@example.com", + "gene\@example.com", + "paul\@example.com", + "peter\@example.com", +); + + +# ======================================================================== +# ====== Probably you don't need to touch anything below this line ====== +# ======================================================================== + +# Black theme +our %BLACK = ( + "canvas" => "#000000", + "back" => "#101010", + "font" => "#C0C0C0", + "mgrid" => "#80C080", + "grid" => "#808020", + "frame" => "#808080", + "arrow" => "#FFFFFF", + "shadea" => "#404040", + "shadeb" => "#404040", + "axis" => "#101010", + "main_bg" => "#000000", + "main_fg" => "#FFFFFF", + "title_bg" => "#333333", + "title_fg" => "#888800", + "graph_bg" => "#888888", +); + +our %GRAPH_SIZE = ( + "main" => "450x150", + "medium" => "325x150", + "medium2" => "325x70", + "small" => "200x66", + "mini" => "183x66", + "tiny" => "110x40", + "zoom" => "800x300", + "remote" => "300x100", +); + +our @GRAPH_NAME = ( + "system", + "kern", + "proc", + "hptemp", + "lmsens", + "nvidia", + "disk", + "fs", + "net", + "serv", + "mail", + "port", + "user", + "apache", + "nginx", + "lighttpd", + "mysql", + "squid", + "nfss", + "nfsc", + "bind", + "ntp", + "fail2ban", + "icecast", + "int", +); + +our %GRAPH_TITLE = ( + "system" => "System load average and usage", + "kern" => "Global kernel usage", + "proc" => "Kernel usage per processor", + "hptemp" => "HP ProLiant System Health", + "lmsens" => "LM-Sensors and GPU temperatures", + "nvidia" => "NVIDIA temperatures and usage", + "disk" => "Disk drive temperatures and health", + "fs" => "Filesystem usage and I/O activity", + "net" => "Network traffic and usage", + "serv" => "System services demand", + "mail" => "Mail statistics", + "port" => "Network port traffic", + "user" => "Users using the system", + "apache" => "Apache statistics", + "nginx" => "Nginx statistics", + "lighttpd" => "Lighttpd statistics", + "mysql" => "MySQL statistics", + "squid" => "Squid statistics", + "nfss" => "NFS server statistics", + "nfsc" => "NFS client statistics", + "bind" => "BIND statistics", + "ntp" => "NTP statistics", + "fail2ban" => "Fail2ban statistics", + "icecast" => "Icecast Streaming Media Server", + "int" => "Devices interrupt activity", +); + +our %GRAPHS = ( + "System load" => "_system1", + "Active processes" => "_system2", + "Memory allocation" => "_system3", + "Kernel usage" => "_kern1", + "Context switches and forks" => "_kern2", + "VFS usage" => "_kern3", + "Processor" => "_proc", + "Temperatures 1" => "_hptemp1", + "Temperatures 2" => "_hptemp2", + "Temperatures 3" => "_hptemp3", + "Core temperatures" => "_lmsens1", + "Voltages" => "_lmsens2", + "MB and CPU temperatures" => "_lmsens3", + "Fan speeds" => "_lmsens4", + "GPU temperatures" => "_lmsens5", + "NVIDIA temperatures" => "_nvidia1", + "CPU usage" => "_nvidia2", + "Memory usage" => "_nvidia3", + "Disk drives temperatures" => "_disk1", + "Reallocated sector count" => "_disk2", + "Current pending sector" => "_disk3", + "Filesystems usage" => "_fs1", + "Disk I/O activity" => "_fs2", + "Time spent in I/O activity" => "_fs3", + "Network traffic" => "_net1", + "Network packets" => "_net2", + "Network errors" => "_net3", + "System services demand" => "_serv1", + "IMAP and POP3 services" => "_serv2", + "SMTP service" => "_serv3", + "Mail statistics" => "_mail1", + "Network traffic" => "_mail2", + "Mails in queue" => "_mail3", + "Queue size" => "_mail4", + "Greylisting" => "_mail5", + "Port" => "_port", + "Users logged in" => "_user1", + "Samba users" => "_user2", + "Netatalk users" => "_user3", + "Apache workers" => "_apache1", + "Apache CPU usage" => "_apache2", + "Apache requests" => "_apache3", + "Nginx connections" => "_nginx1", + "Nginx requests" => "_nginx2", + "Nginx traffic" => "_nginx3", + "Lighttpd workers" => "_lighttpd1", + "Lighttpd traffic" => "_lighttpd2", + "Lighttpd requests" => "_lighttpd3", + "MySQL query types" => "_mysql1", + "MySQL overall stats" => "_mysql2", + "Table saturation and MyISAM" => "_mysql3", + "MySQL queries" => "_mysql4", + "MySQL connections" => "_mysql5", + "MySQL traffic" => "_mysql6", + "Squid statistics 1" => "_squid1", + "Squid statistics 2" => "_squid2", + "Overall I/O" => "_squid3", + "Memory usage" => "_squid4", + "Store directory stats" => "_squid5", + "IP cache stats" => "_squid6", + "Network protocols usage" => "_squid7", + "Client traffic" => "_squid8", + "Server traffic" => "_squid9", + "NFS server stats 1" => "_nfss1", + "NFS server stats 2" => "_nfss2", + "NFS server stats 3" => "_nfss3", + "Overall I/O" => "_nfss4", + "Network layer" => "_nfss5", + "RPC" => "_nfss6", + "Thread utilization" => "_nfss7", + "Read cache" => "_nfss8", + "File handle cache" => "_nfss9", + "NFS client stats 1" => "_nfsc1", + "NFS client stats 2" => "_nfsc2", + "NFS client stats 3" => "_nfsc3", + "NFS client stats 4" => "_nfsc4", + "NFS client stats 5" => "_nfsc5", + "RPC client stats" => "_nfsc6", + "Incoming queries" => "_bind1", + "Outgoing queries (_default)" => "_bind2", + "Name server statistics" => "_bind3", + "Resolver statistics (_default)" => "_bind4", + "Cache DB RRsets (_default)" => "_bind5", + "Memory usage" => "_bind6", + "Task manager" => "_bind7", + "NTP timing stats" => "_ntp1", + "Stratum level" => "_ntp2", + "Codes" => "_ntp3", + "Fail2ban jails" => "_fail2ban", + "Current Listeners" => "_icecast1", + "Bitrate" => "_icecast2", + "Interrupt activity" => "_int1", + "Core activity" => "_int2", + "Interrupt activity" => "_int3", +); + +our $TIMEOUT = 15; + +our $IMGS_DIR = "imgs/"; +our $USAGE_DIR = $BASE_LIB . "usage/"; +our $REPORT_DIR = $BASE_LIB . "reports/"; +our $PNG_DIR = $BASE_DIR . $IMGS_DIR; +our $FAVICON = $BASE_URL . "/monitorixico.png"; + +our $SYSTEM_RRD = $BASE_LIB . "system.rrd"; +our $KERN_RRD = $BASE_LIB . "kern.rrd"; +our $PROC_RRD = $BASE_LIB . "proc.rrd"; +our $HPTEMP_RRD = $BASE_LIB . "hptemp.rrd"; +our $LMSENS_RRD = $BASE_LIB . "lmsens.rrd"; +our $NVIDIA_RRD = $BASE_LIB . "nvidia.rrd"; +our $DISK_RRD = $BASE_LIB . "disk.rrd"; +our $FS_RRD = $BASE_LIB . "fs.rrd"; +our $NET_RRD = $BASE_LIB . "net.rrd"; +our $SERV_RRD = $BASE_LIB . "serv.rrd"; +our $MAIL_RRD = $BASE_LIB . "mail.rrd"; +our $PORT_RRD = $BASE_LIB . "port.rrd"; +our $USER_RRD = $BASE_LIB . "user.rrd"; +our $APACHE_RRD = $BASE_LIB . "apache.rrd"; +our $NGINX_RRD = $BASE_LIB . "nginx.rrd"; +our $LIGHTTPD_RRD = $BASE_LIB . "lighttpd.rrd"; +our $MYSQL_RRD = $BASE_LIB . "mysql.rrd"; +our $SQUID_RRD = $BASE_LIB . "squid.rrd"; +our $NFSS_RRD = $BASE_LIB . "nfss.rrd"; +our $NFSC_RRD = $BASE_LIB . "nfsc.rrd"; +our $BIND_RRD = $BASE_LIB . "bind.rrd"; +our $NTP_RRD = $BASE_LIB . "ntp.rrd"; +our $FAIL2BAN_RRD = $BASE_LIB . "fail2ban.rrd"; +our $ICECAST_RRD = $BASE_LIB . "icecast.rrd"; +our $INT_RRD = $BASE_LIB . "int.rrd"; +our $PC_RRD = $BASE_LIB . "pc.rrd"; diff --git a/monitorixico.png b/monitorixico.png new file mode 100644 index 0000000000000000000000000000000000000000..506205596e7233d30409eb233da9a364deacc760 GIT binary patch literal 2251 zcmY*aOKe+36g~5ve{pOlZqt1FPiavp^n;2hg;I$&RU4sJfLMT#5JIp9i7r5F5UgO! z0(Ky=C~Od7gG9wgg$fnavOrNqp&vDAQYTLQssGP@!?|~CC)|-|-n(<>ymLQu{oylb zPNtI^lK|4wr>36cx`DrmM2z!|nb()O#9n>+9R_Y;2wE*x{2MM!=T0Y`J z?lw4A!m65SGF?iQvAkDpMeP*y-}#!oouiwcK^R&jq8`!-Zt+=8EEJk*yoelX=AMGY z5JMUnWhfveTg30-C8eOC%cTINsxUR^bSyTHCh)-aK?h3UpZ+YW@vp%JyJ#2n0~^g2 z?DG#WnwIVwv}_0S;oK_Ia-)MrGlU^i5Oh2n#g4H7pzVCWeC?hZ|81}09y2PD8!;o; zW$uTh(Qt^aY)fjVO!Eb9l>_))(6MX`ySMR{bX?%C->Iu{&fe8kw4>e_M$Nd!-jJ)L za~Vszub|B~&B#iVPj?3y&rKr2A3bXk(5 zLi~vDVee!LCgp0+cHCNJl0>9P4tY-yG^6j`lV}p-GS~LhGN{W(~f4oy9Wu!2yfQ-Isv5@)+gKo3SM4K5;l%8 zj5Fi^zZeyib>9o9pIszVmXnHL@Fy}POey8E#l^Y1w(Zw7?#4KSw&q?j1<%K$pTC8_xWBuUcumrDEW%|2?FHEECP`frJE)xmEDc@b)ZaK&|MUr5%p`_TSBv8`! z1eArzqAJ3hlfv(plSQ0~+POLTh#V48O0K5akycG*FXg3?G`@mLQxR#I7QCgR%e-o2 zqMI>RLQl4i(?#hG6uE?l{fG5gCwd?qUzqkpS^ssDSFKx@vL}&<^qAA~vE4&`P;u{Q z&O4p(W^kv)@xSeJ<)!`f^Re3ZR(txO$USJ?JwA-jG1ZmeKE_IRtHW8MUw^pB## h5yJrTCWi^L8Q;XOy=#|S9|+F$i8E7QAA9Bf{{T??{ulrN literal 0 HcmV?d00001 diff --git a/reports/ca.html b/reports/ca.html new file mode 100644 index 0000000..f4c73f9 --- /dev/null +++ b/reports/ca.html @@ -0,0 +1,74 @@ + + + Monitorix: Informe de tràfic d'Internet + + + + + + + + + + + + + + + + + + + + +
+ Monitorix +
+
+

+

+

+

+ +Estimat usuari, +

+Tot seguit us presentem les dades de l'informe mensual corresponent al tràfic d'Internet produït pel vostre ordinador: +

+
+ +
+
+ + +trafic mensual d'Internet + + +
+
+
+
+
+      
+ +Aprofitem l'avinentesa per agraïr-vos la vostra confiança. +
+
+
+ + + + + +
+ +Atentament, +
+El vostre nom aquí +
+you@example.com
+http://www.example.com +
+
+
+ + diff --git a/reports/de.html b/reports/de.html new file mode 100644 index 0000000..9727cb1 --- /dev/null +++ b/reports/de.html @@ -0,0 +1,74 @@ + + + Monitorix: Internet-Datendurchsatz Bericht + + + + + + + + + + + + + + + + + + + + +
+ Monitorix +
+
+

+

+

+

+ +Sehr geehrter Benutzer, +

+Die Grafiken zeigen Ihnen den Internetdatendurchsatz ihres Computers im letzten Monat: +

+
+ +
+
+ + +Monatlicher Internet Datendurchsatz + + +
+
+
+
+
+      
+ +Vielen Dank für Ihre Aufmerksamkeit. +
+
+
+ + + + + +
+ +mit freundlichen Grüßen, +
+Ihr name hier +
+you@example.com
+http://www.example.com +
+
+
+ + diff --git a/reports/en.html b/reports/en.html new file mode 100644 index 0000000..2472cff --- /dev/null +++ b/reports/en.html @@ -0,0 +1,74 @@ + + + Monitorix: Internet Traffic Report + + + + + + + + + + + + + + + + + + + + +
+ Monitorix +
+
+

+

+

+

+ +Dear user, +

+The graph presented below shows the Internet traffic generated by your computer during the last month: +

+
+ +
+
+ + +Internet monthly traffic + + +
+
+
+
+
+      
+ +Thank you for your confidence. +
+
+
+ + + + + +
+ +Sincerely, +
+Your name here +
+you@example.com
+http://www.example.com +
+
+
+ + diff --git a/reports/it.html b/reports/it.html new file mode 100644 index 0000000..e8fc124 --- /dev/null +++ b/reports/it.html @@ -0,0 +1,74 @@ + + + Monitorix: Report del Traffico Internet + + + + + + + + + + + + + + + + + + + + +
+ Monitorix +
+
+

+

+

+

+ +Gentile utente, +

+Il grafico seguente mostra il traffico internet generato dal tuo computer durante l'ultimo mese: +

+
+ +
+
+ + +Traffico mensile internet + + +
+
+
+
+
+      
+ +Ti ringraziamo per averci scelto! +
+
+
+ + + + + +
+ +Cordiali Saluti, +
+qui il tuo nome +
+you@example.com
+http://www.example.com +
+
+
+ + diff --git a/reports/pl.html b/reports/pl.html new file mode 100644 index 0000000..c399e69 --- /dev/null +++ b/reports/pl.html @@ -0,0 +1,74 @@ + + + Monitorix: Raport użycia Internetu + + + + + + + + + + + + + + + + + + + + +
+ Monitorix +
+
+

+

+

+

+ +Drogi użytkowniku, +

+Wykres zamieszczony poniżej pokazuje użycie łącza internetowego wygenerowane przez Twój komputer w ciągu ostatniego miesiąca: +

+
+ +
+
+ + +Miesięczny ruch Internetowy + + +
+
+
+
+
+      
+ +Dziękujemy za zaufanie. +
+
+
+ + + + + +
+ +Z poważaniem, +
+Tutaj Twoja nazwa +
+ty@domena.com
+http://www.domena.com +
+
+
+ + diff --git a/reports/send_reports b/reports/send_reports new file mode 100755 index 0000000..a7eefc1 --- /dev/null +++ b/reports/send_reports @@ -0,0 +1,165 @@ +#!/usr/bin/perl +# +# Monitorix - Sends Monitorix monthly reports. +# +# Copyright (C) 2005-2012 by Jordi Sanfeliu +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +require 5.006; + +no strict "vars"; +no warnings "once"; +#use warnings; +use LWP::UserAgent; +use Getopt::Long; +use MIME::Lite; + +use constant SMTP_HOST => "localhost"; +use constant FROM => "noreply\@example.com"; +use constant PREFIX => "http://127.0.0.1"; +use constant SUBJECT => "Monitorix: monthly traffic report"; + +# ======================================================================== +# ====== Probably you don't need to touch anything below this line ====== +# ======================================================================== + +my $url; +my $ua; +my (undef, undef, undef, undef, $prev_month, $prev_year) = localtime(time - 3600); + +sub adjust($) { + my $bytes = (shift); + my $adjust = 0; + my $b = " "; + + if($bytes > 0 && $bytes < 1048576) { + $adjust = $bytes/1024; + $b = "KB"; + } + if($bytes > 1048576 && $bytes < 1073741824) { + $adjust = $bytes/1024/1024; + $b = "MB"; + } + if($bytes > 1073741824 && $bytes < 1000000000000) { + $adjust = $bytes/1024/1024/1024; + $b = "GB"; + } + return sprintf("%3u%s", $adjust, $b); +} + +GetOptions( + "host=s" => \$opt_host, + "config=s" => \$opt_config, +); +if(!$opt_host || !$opt_config) { + die("send_reports -h|--host -c|--config \n\n"); +} +if(!stat($opt_config)) { + die("can't open file $opt_config.\n"); +} +# load configuration file +require $opt_config; + + +# get the traffic counters +# ----------------------------------------------------------------------------- +my @traffic = (); +my $tot_in = 0; +my $tot_out = 0; +my $tot = 0; +open(IN, $USAGE_DIR . $opt_host); +push(@traffic, "DAY INPUT OUTPUT TOTAL\n"); +push(@traffic, "---------------------------------------------------------------\n"); +while() { + my ($day, $in, $out) = split(' ', $_); + chomp($day); + chomp($in); + chomp($day); + $tot_in += $in; + $tot_out += $out; + $tot = $in + $out; + push(@traffic, sprintf("%3u %12u %s %12u %s %15u %s\n", $day, $in, adjust($in), $out, adjust($out), $tot, adjust($tot))); +} +close(IN); +push(@traffic, "---------------------------------------------------------------\n"); +$tot = $tot_in + $tot_out; +push(@traffic, sprintf("%16u %s %12u %s %15u %s\n", $tot_in, adjust($tot_in), $tot_out, adjust($tot_out), $tot, adjust($tot))); + + +# get the recipient's email address +# ----------------------------------------------------------------------------- +my %index; +@index{@PC_LIST} = (0 .. $#PC_LIST); +my $i = $index{$opt_host}; +my $to_addr = $PC_LIST[$i]; +$to_addr = $PC_DEFAULT_MAIL unless $PC_REPORT_MAIL[$i]; + + +# get the Monitorix logo +# ----------------------------------------------------------------------------- +$url = PREFIX . $BASE_URL . "/logo_bot.png"; +$ua = LWP::UserAgent->new(timeout => 30); +my $logo = $ua->request(HTTP::Request->new('GET', $url)); + + +# get the monthly graph +# ----------------------------------------------------------------------------- +$url = PREFIX . $BASE_CGI . "/monitorix.cgi?mode=pc.$i&graph=all&when=month&color=$THEME_COLOR&silent=imagetagbig"; +$ua = LWP::UserAgent->new(timeout => 30); +$ua->request(HTTP::Request->new('GET', $url)); +$url = PREFIX . $BASE_URL . "/" . $IMGS_DIR . "pc" . $i . ".month.png"; +my $graph = $ua->request(HTTP::Request->new('GET', $url)); + + +# create the multipart container, add attachments and send the message +# ----------------------------------------------------------------------------- +$msg = new MIME::Lite( + From => FROM, + To => $to_addr, + Subject => SUBJECT . " - $opt_host", + Type => "multipart/related", + Organization => "Monitorix", +); + +$msg->attach( + Type => 'text/html', + Path => $PC_REPORT_LANG . '.html', +); +$msg->attach( + Type => 'image/png', + Id => 'image_01', + Data => $logo->content, +); +$msg->attach( + Type => 'image/png', + Id => 'image_02', + Data => $graph->content, +); +$msg->attach( + Type => 'text/plain', + Id => 'text_01', + Data => join("", @traffic), +); + +$msg->send('smtp', SMTP_HOST, Timeout => 60); + + +# rename $opt_host file to avoid reusing +# ----------------------------------------------------------------------------- +my $newname = sprintf("%s.%02u-%u", $USAGE_DIR . $opt_host, $prev_month + 1, $prev_year + 1900); +rename($USAGE_DIR . $opt_host, $newname); +