├── CODEOWNERS ├── CONTRIBUTING-ARCHIVED.md ├── LICENSE.txt ├── LinuxTelemetryDashboard.png ├── README.md ├── docs ├── Makefile ├── _build │ ├── doctrees │ │ ├── buddyinfo.doctree │ │ ├── diskstats.doctree │ │ ├── environment.pickle │ │ ├── fusionio.doctree │ │ ├── index.doctree │ │ ├── netstats.doctree │ │ ├── vmstats.doctree │ │ └── zoneinfo.doctree │ └── html │ │ ├── .buildinfo │ │ ├── _modules │ │ ├── buddyinfo.html │ │ ├── diskstats.html │ │ ├── fusionio.html │ │ ├── index.html │ │ ├── netstats.html │ │ ├── vmstats.html │ │ └── zoneinfo.html │ │ ├── _sources │ │ ├── buddyinfo.txt │ │ ├── diskstats.txt │ │ ├── fusionio.txt │ │ ├── index.txt │ │ ├── netstats.txt │ │ ├── vmstats.txt │ │ └── zoneinfo.txt │ │ ├── _static │ │ ├── ajax-loader.gif │ │ ├── basic.css │ │ ├── classic.css │ │ ├── comment-bright.png │ │ ├── comment-close.png │ │ ├── comment.png │ │ ├── default.css │ │ ├── doctools.js │ │ ├── down-pressed.png │ │ ├── down.png │ │ ├── file.png │ │ ├── jquery-1.11.1.js │ │ ├── jquery.js │ │ ├── minus.png │ │ ├── plus.png │ │ ├── pygments.css │ │ ├── searchtools.js │ │ ├── sidebar.js │ │ ├── underscore-1.3.1.js │ │ ├── underscore.js │ │ ├── up-pressed.png │ │ ├── up.png │ │ └── websupport.js │ │ ├── buddyinfo.html │ │ ├── diskstats.html │ │ ├── fusionio.html │ │ ├── genindex.html │ │ ├── index.html │ │ ├── netstats.html │ │ ├── objects.inv │ │ ├── py-modindex.html │ │ ├── search.html │ │ ├── searchindex.js │ │ ├── vmstats.html │ │ └── zoneinfo.html ├── buddyinfo.rst ├── conf.py ├── diskstats.rst ├── fusionio.rst ├── index.rst ├── make.bat ├── netstats.rst ├── vmstats.rst └── zoneinfo.rst ├── plugins ├── __init__.py ├── buddyinfo.conf ├── buddyinfo.py ├── diskstats.conf ├── diskstats.py ├── fusionio.conf ├── fusionio.py ├── netstats.conf ├── netstats.py ├── vmstats.conf ├── vmstats.py ├── zoneinfo.conf └── zoneinfo.py ├── setup.py └── tests ├── buddyinfo_utest.py ├── collectd.py ├── diskstats_ftest.py ├── diskstats_utest.py ├── netstats_ftest.py ├── netstats_utest.py ├── vmstats_ftest.py ├── vmstats_utest.py └── zoneinfo_utest.py /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Comment line immediately above ownership line is reserved for related gus information. Please be careful while editing. 2 | #ECCN:Open Source 3 | -------------------------------------------------------------------------------- /CONTRIBUTING-ARCHIVED.md: -------------------------------------------------------------------------------- 1 | # ARCHIVED 2 | 3 | This project is `Archived` and is no longer actively maintained; 4 | We are not accepting contributions or Pull Requests. 5 | 6 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Salesforce.com, Inc. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | 8 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 9 | 10 | * Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 11 | 12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 13 | -------------------------------------------------------------------------------- /LinuxTelemetryDashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salesforce/LinuxTelemetry/37027505489f2719070c98320f5805ceda3b0824/LinuxTelemetryDashboard.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Linux Telemetry Plugins 2 | ======================= 3 | 4 | Linux exposes detailed sub-system and device level statistics through procfs and sysfs. These statistics are useful for system debugging as well as performance tuning. These statistics are often consumed through one-off analysis scripts or a number of command-line tools, such as, vmstat, iostat, netstat, sar, atop, collectl, numastat, and so on. There is a need to capture these statistics 24x7 in a cloud environment to support system health monitoring and alerting, live site incident triage and investigations, performance debugging, and capacity monitoring and planning. 5 | 6 | This repo provides a number of Collectd plugins for detailed monitoring of a typical Linux server at device and sub-system 7 | levels. These python based plugins extend base collectd to monitor network, disk, flash, RAID, virtual memory, NUMA nodes, memory allocation zones, and buddy allocator metrics. 8 | 9 | Following plugins are being provided: 10 | 11 | - [Diskstats](plugins/diskstats.py) 12 | - [Fusion-io](plugins/fusionio.py) 13 | - [Vmstats](plugins/vmstats.py) 14 | - [Buddyinfo](plugins/buddyinfo.py) 15 | - [Zoneinfo](plugins/zoneinfo.py) 16 | - [Netstats](plugins/netstats.py) 17 | 18 | Except for fusion-io plugin, all others gather system level metrics through procfs from corresponding locations: /proc/diskstats, /proc/vmstats, /proc/buddyinfo, /proc/zoneinfo, /proc/net/snmp, and /proc/net/netstat. 19 | 20 | Installation 21 | ------------ 22 | 23 | Installation process is tested on Red Hat Enterprise Linux Server 24 | release 6.5. It will need to be adapted for other variants of Linux. 25 | 26 | ### Step 1. Base collectd installation with python: 27 | 28 | Base [collectd](https://collectd.org/download.shtml) is available as RPM packages. If yum repo is configured for collectd installation: 29 | 30 | `sudo yum install collectd libcollectdclient collectd-python` 31 | 32 | For target systems for which RPM packages are not available, it is possible to install base collectd directly from source (install any dependencies, such as libtool-ltdl-devel and possibly others depending on system setup, along the way): 33 | 34 | ``` 35 | git clone https://github.com/collectd/collectd.git 36 | cd collectd 37 | ./build.sh 38 | ./configure --prefix=/usr --sysconfdir=/etc --libdir=/usr/lib --mandir=/usr/share/man --enable-python 39 | make 40 | sudo make install 41 | sudo cp contrib/redhat/init.d-collectd /etc/init.d/collectd 42 | sudo chmod +x /etc/init.d/collectd 43 | ``` 44 | 45 | Edit collectd configuration in /etc/collectd.conf to allow it to use external plugin configurations by adding following lines to it: 46 | 47 | ``` 48 | 49 | Filter "*.conf" 50 | 51 | ``` 52 | 53 | ### Step 2. Installation of telemetry plugins: 54 | 55 | Install plugins using: 56 | 57 | ``` 58 | git clone https://github.com/SalesforceEng/LinuxTelemetry.git 59 | cd LinuxTelemetry 60 | sudo python setup.py install 61 | ``` 62 | 63 | This install script requires that base collectd is already installed with 64 | following files/directories: 65 | 66 | 1. /etc/collectd.conf 67 | 2. /etc/collectd.d (for plugin in conf files) 68 | 3. /usr/share/collectd/types.db 69 | 4. /usr/share/collectd/plugins/python (for python plugins) 70 | 71 | 72 | ### Step 3. Start/restart collectd: 73 | 74 | `service collectd start` (or `collectd -C /etc/collectd.conf`) 75 | 76 | 77 | Testing 78 | ------- 79 | 80 | In order to test the measurements that these plugins gather, enable 81 | CSV plugin from collectd.conf to print the values in text files. 82 | 83 | ``` 84 | LoadPlugin csv 85 | 86 | DataDir "/var/lib/collectd/csv" 87 | 88 | ``` 89 | 90 | Multiple collectd supported tools can forward measurements from target 91 | hosts to an aggregation point in a cloud environment for continuous remote 92 | monitoring. For instance, Graphite/Carbon can be used for forwarding and 93 | visualization of collectd metrics. Collectd comes with wrie_graphite plugin, 94 | which can be enabled in collectd.conf to forward metrics to host(s) running 95 | Graphite/Carbon as follows: 96 | 97 | ``` 98 | LoadPlugin write_graphite 99 | 100 | 101 | Host "localhost" 102 | Port "2003" 103 | Protocol "tcp" 104 | LogSendErrors true 105 | Prefix "Linux" 106 | Postfix "Telemetry" 107 | StoreRates true 108 | AlwaysAppendDS false 109 | EscapeCharacter "_" 110 | 111 | 112 | ``` 113 | 114 | ![Linux Telemetry Dashboard](/LinuxTelemetryDashboard.png?raw=true) 115 | 116 | Installing Graphite is often a time-consuming process due to complex dependencies. A simpler alternative is to use a Vagrant/VirtualBox guest bundled with Graphite. See for example [this](https://github.com/pkkummermo/grafana-vagrant-puppet-box) implementation. 117 | 118 | Plugins 119 | ------- 120 | 121 | ### Diskstats 122 | 123 | This plug-in reads /proc/diskstats and collects stats for devices, such as disks, RAID, flash, etc. In addition to collecting raw stats, plugin can derive metrics such as, iops, device utilization, bytes read/write volumes, queue sizes, service times, and so on at next collection interval. These metrics are typically obtained through 'iostat', 'sar', or 'atop'. 124 | 125 | ### Fusion-IO 126 | 127 | This plugin is specifically developed for fusion-io flash device measurement. It currently measures: 128 | 129 | - physical blocks read 130 | - physical blocks written 131 | - total blocks 132 | - min block erases count 133 | - max block erases count 134 | - average block erases count 135 | 136 | These metrics are extracted from fusion-io command-line utilities: 'fio-status' and 'fio-get-erase-count'. 137 | 138 | ### Vmstats 139 | 140 | This plugin is based on /proc/vmstat raw metrics. In addition to raw metrics, a few metric are derived, which are available through tools such as 'vmstat', 'sar' and 'atop': 141 | 142 | - pgpgin/s 143 | - pgpgout/s 144 | - fault/s 145 | - majflt/s 146 | - pgfree/s 147 | - pgscank/s 148 | - pgscand/s 149 | - pgsteal/s 150 | - %vmeff 151 | 152 | ### Buddyinfo 153 | 154 | Linux uses buddy allocator for memory management. This plugin is based on the number of free pages counters from /proc/buddyinfo. These free pages statistics are available in terms of NUMA node, allocation zones (such as Normal, DMA, etc.), and order of page sizes: 4K, 8K, 16K, 32K, 64K, 128K, 256K, 512K, 1024K, and 2048K. These statistics are useful for getting a handle on memory pressure, fragmentation, and virtual memory system in-efficiences, and JVM/GC pauses. Such statistics are typically obtained from tools such as 'collectl'. 155 | 156 | ### Zoneinfo 157 | 158 | This plugin extracts metrics freom /proc/zoneinfo, which essentially breaks down virtual memory stats with respect to each NUMA node and memory zone. It supplements the measurements provided by vmstta and buddyinfo plugins with respect to zones. 159 | 160 | ### Netstats 161 | 162 | Linux maintains network protocol specific counters under /proc/net/snmp and /proc/net/netstat. Protocols include IP, ICMP, TCP, UDP, and their extensions. This plugin exposes those counters, which are typically available through 'netstat -s' command for net-tools implementation of netstat. 163 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # Internal variables. 11 | PAPEROPT_a4 = -D latex_paper_size=a4 12 | PAPEROPT_letter = -D latex_paper_size=letter 13 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 14 | # the i18n builder cannot share the environment and doctrees with the others 15 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 16 | 17 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext 18 | 19 | help: 20 | @echo "Please use \`make ' where is one of" 21 | @echo " html to make standalone HTML files" 22 | @echo " dirhtml to make HTML files named index.html in directories" 23 | @echo " singlehtml to make a single large HTML file" 24 | @echo " pickle to make pickle files" 25 | @echo " json to make JSON files" 26 | @echo " htmlhelp to make HTML files and a HTML help project" 27 | @echo " qthelp to make HTML files and a qthelp project" 28 | @echo " devhelp to make HTML files and a Devhelp project" 29 | @echo " epub to make an epub" 30 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 31 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 32 | @echo " text to make text files" 33 | @echo " man to make manual pages" 34 | @echo " texinfo to make Texinfo files" 35 | @echo " info to make Texinfo files and run them through makeinfo" 36 | @echo " gettext to make PO message catalogs" 37 | @echo " changes to make an overview of all changed/added/deprecated items" 38 | @echo " linkcheck to check all external links for integrity" 39 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 40 | 41 | clean: 42 | -rm -rf $(BUILDDIR)/* 43 | 44 | html: 45 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 46 | @echo 47 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 48 | 49 | dirhtml: 50 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 51 | @echo 52 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 53 | 54 | singlehtml: 55 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 56 | @echo 57 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 58 | 59 | pickle: 60 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 61 | @echo 62 | @echo "Build finished; now you can process the pickle files." 63 | 64 | json: 65 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 66 | @echo 67 | @echo "Build finished; now you can process the JSON files." 68 | 69 | htmlhelp: 70 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 71 | @echo 72 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 73 | ".hhp project file in $(BUILDDIR)/htmlhelp." 74 | 75 | qthelp: 76 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 77 | @echo 78 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 79 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 80 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/plugins.qhcp" 81 | @echo "To view the help file:" 82 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/plugins.qhc" 83 | 84 | devhelp: 85 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 86 | @echo 87 | @echo "Build finished." 88 | @echo "To view the help file:" 89 | @echo "# mkdir -p $$HOME/.local/share/devhelp/plugins" 90 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/plugins" 91 | @echo "# devhelp" 92 | 93 | epub: 94 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 95 | @echo 96 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 97 | 98 | latex: 99 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 100 | @echo 101 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 102 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 103 | "(use \`make latexpdf' here to do that automatically)." 104 | 105 | latexpdf: 106 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 107 | @echo "Running LaTeX files through pdflatex..." 108 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 109 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 110 | 111 | text: 112 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 113 | @echo 114 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 115 | 116 | man: 117 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 118 | @echo 119 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 120 | 121 | texinfo: 122 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 123 | @echo 124 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 125 | @echo "Run \`make' in that directory to run these through makeinfo" \ 126 | "(use \`make info' here to do that automatically)." 127 | 128 | info: 129 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 130 | @echo "Running Texinfo files through makeinfo..." 131 | make -C $(BUILDDIR)/texinfo info 132 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 133 | 134 | gettext: 135 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 136 | @echo 137 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 138 | 139 | changes: 140 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 141 | @echo 142 | @echo "The overview file is in $(BUILDDIR)/changes." 143 | 144 | linkcheck: 145 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 146 | @echo 147 | @echo "Link check complete; look for any errors in the above output " \ 148 | "or in $(BUILDDIR)/linkcheck/output.txt." 149 | 150 | doctest: 151 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 152 | @echo "Testing of doctests in the sources finished, look at the " \ 153 | "results in $(BUILDDIR)/doctest/output.txt." 154 | -------------------------------------------------------------------------------- /docs/_build/doctrees/buddyinfo.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salesforce/LinuxTelemetry/37027505489f2719070c98320f5805ceda3b0824/docs/_build/doctrees/buddyinfo.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/diskstats.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salesforce/LinuxTelemetry/37027505489f2719070c98320f5805ceda3b0824/docs/_build/doctrees/diskstats.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/environment.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salesforce/LinuxTelemetry/37027505489f2719070c98320f5805ceda3b0824/docs/_build/doctrees/environment.pickle -------------------------------------------------------------------------------- /docs/_build/doctrees/fusionio.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salesforce/LinuxTelemetry/37027505489f2719070c98320f5805ceda3b0824/docs/_build/doctrees/fusionio.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/index.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salesforce/LinuxTelemetry/37027505489f2719070c98320f5805ceda3b0824/docs/_build/doctrees/index.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/netstats.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salesforce/LinuxTelemetry/37027505489f2719070c98320f5805ceda3b0824/docs/_build/doctrees/netstats.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/vmstats.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salesforce/LinuxTelemetry/37027505489f2719070c98320f5805ceda3b0824/docs/_build/doctrees/vmstats.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/zoneinfo.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salesforce/LinuxTelemetry/37027505489f2719070c98320f5805ceda3b0824/docs/_build/doctrees/zoneinfo.doctree -------------------------------------------------------------------------------- /docs/_build/html/.buildinfo: -------------------------------------------------------------------------------- 1 | # Sphinx build info version 1 2 | # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. 3 | config: 697bc8fc97fcf3243fca5392d4bc5feb 4 | tags: fbb0d17656682115ca4d033fb2f83ba1 5 | -------------------------------------------------------------------------------- /docs/_build/html/_modules/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Overview: module code — LinuxTelemetry 1 documentation 12 | 13 | 14 | 15 | 16 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 43 | 44 |
45 |
46 |
47 |
48 | 49 |

All modules for which code is available

50 | 57 | 58 |
59 |
60 |
61 |
62 |
63 | 75 | 76 |
77 |
78 |
79 |
80 | 92 | 96 | 97 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/buddyinfo.txt: -------------------------------------------------------------------------------- 1 | buddyinfo Module 2 | ================ 3 | 4 | .. automodule:: buddyinfo 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/diskstats.txt: -------------------------------------------------------------------------------- 1 | diskstats Module 2 | ================ 3 | 4 | .. automodule:: diskstats 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/fusionio.txt: -------------------------------------------------------------------------------- 1 | fusionio Module 2 | =============== 3 | 4 | .. automodule:: fusionio 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/index.txt: -------------------------------------------------------------------------------- 1 | .. plugins documentation master file, created by 2 | sphinx-quickstart on Sat Jan 2 21:49:11 2016. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to LinuxTelemetry's documentation! 7 | ========================================== 8 | 9 | Linux procfs maintains a large number of system metrics that are used for monitoring and debugging system health and performance. We have developed a number of collectd plugins to capture metrics related to memory, storage devices, and networking protocols. Continuous collection of these metrics is critical for cloud infrastructure monitoring, tuning, capacity planning, and analytics 10 | 11 | Contents: 12 | 13 | .. toctree:: 14 | :maxdepth: 4 15 | 16 | buddyinfo 17 | diskstats 18 | fusionio 19 | netstats 20 | vmstats 21 | zoneinfo 22 | 23 | 24 | Indices and tables 25 | ================== 26 | 27 | * :ref:`genindex` 28 | * :ref:`modindex` 29 | * :ref:`search` 30 | 31 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/netstats.txt: -------------------------------------------------------------------------------- 1 | netstats Module 2 | =============== 3 | 4 | .. automodule:: netstats 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/vmstats.txt: -------------------------------------------------------------------------------- 1 | vmstats Module 2 | ============== 3 | 4 | .. automodule:: vmstats 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/zoneinfo.txt: -------------------------------------------------------------------------------- 1 | zoneinfo Module 2 | =============== 3 | 4 | .. automodule:: zoneinfo 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/_build/html/_static/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salesforce/LinuxTelemetry/37027505489f2719070c98320f5805ceda3b0824/docs/_build/html/_static/ajax-loader.gif -------------------------------------------------------------------------------- /docs/_build/html/_static/basic.css: -------------------------------------------------------------------------------- 1 | /* 2 | * basic.css 3 | * ~~~~~~~~~ 4 | * 5 | * Sphinx stylesheet -- basic theme. 6 | * 7 | * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | /* -- main layout ----------------------------------------------------------- */ 13 | 14 | div.clearer { 15 | clear: both; 16 | } 17 | 18 | /* -- relbar ---------------------------------------------------------------- */ 19 | 20 | div.related { 21 | width: 100%; 22 | font-size: 90%; 23 | } 24 | 25 | div.related h3 { 26 | display: none; 27 | } 28 | 29 | div.related ul { 30 | margin: 0; 31 | padding: 0 0 0 10px; 32 | list-style: none; 33 | } 34 | 35 | div.related li { 36 | display: inline; 37 | } 38 | 39 | div.related li.right { 40 | float: right; 41 | margin-right: 5px; 42 | } 43 | 44 | /* -- sidebar --------------------------------------------------------------- */ 45 | 46 | div.sphinxsidebarwrapper { 47 | padding: 10px 5px 0 10px; 48 | } 49 | 50 | div.sphinxsidebar { 51 | float: left; 52 | width: 230px; 53 | margin-left: -100%; 54 | font-size: 90%; 55 | } 56 | 57 | div.sphinxsidebar ul { 58 | list-style: none; 59 | } 60 | 61 | div.sphinxsidebar ul ul, 62 | div.sphinxsidebar ul.want-points { 63 | margin-left: 20px; 64 | list-style: square; 65 | } 66 | 67 | div.sphinxsidebar ul ul { 68 | margin-top: 0; 69 | margin-bottom: 0; 70 | } 71 | 72 | div.sphinxsidebar form { 73 | margin-top: 10px; 74 | } 75 | 76 | div.sphinxsidebar input { 77 | border: 1px solid #98dbcc; 78 | font-family: sans-serif; 79 | font-size: 1em; 80 | } 81 | 82 | div.sphinxsidebar #searchbox input[type="text"] { 83 | width: 170px; 84 | } 85 | 86 | div.sphinxsidebar #searchbox input[type="submit"] { 87 | width: 30px; 88 | } 89 | 90 | img { 91 | border: 0; 92 | } 93 | 94 | /* -- search page ----------------------------------------------------------- */ 95 | 96 | ul.search { 97 | margin: 10px 0 0 20px; 98 | padding: 0; 99 | } 100 | 101 | ul.search li { 102 | padding: 5px 0 5px 20px; 103 | background-image: url(file.png); 104 | background-repeat: no-repeat; 105 | background-position: 0 7px; 106 | } 107 | 108 | ul.search li a { 109 | font-weight: bold; 110 | } 111 | 112 | ul.search li div.context { 113 | color: #888; 114 | margin: 2px 0 0 30px; 115 | text-align: left; 116 | } 117 | 118 | ul.keywordmatches li.goodmatch a { 119 | font-weight: bold; 120 | } 121 | 122 | /* -- index page ------------------------------------------------------------ */ 123 | 124 | table.contentstable { 125 | width: 90%; 126 | } 127 | 128 | table.contentstable p.biglink { 129 | line-height: 150%; 130 | } 131 | 132 | a.biglink { 133 | font-size: 1.3em; 134 | } 135 | 136 | span.linkdescr { 137 | font-style: italic; 138 | padding-top: 5px; 139 | font-size: 90%; 140 | } 141 | 142 | /* -- general index --------------------------------------------------------- */ 143 | 144 | table.indextable { 145 | width: 100%; 146 | } 147 | 148 | table.indextable td { 149 | text-align: left; 150 | vertical-align: top; 151 | } 152 | 153 | table.indextable dl, table.indextable dd { 154 | margin-top: 0; 155 | margin-bottom: 0; 156 | } 157 | 158 | table.indextable tr.pcap { 159 | height: 10px; 160 | } 161 | 162 | table.indextable tr.cap { 163 | margin-top: 10px; 164 | background-color: #f2f2f2; 165 | } 166 | 167 | img.toggler { 168 | margin-right: 3px; 169 | margin-top: 3px; 170 | cursor: pointer; 171 | } 172 | 173 | div.modindex-jumpbox { 174 | border-top: 1px solid #ddd; 175 | border-bottom: 1px solid #ddd; 176 | margin: 1em 0 1em 0; 177 | padding: 0.4em; 178 | } 179 | 180 | div.genindex-jumpbox { 181 | border-top: 1px solid #ddd; 182 | border-bottom: 1px solid #ddd; 183 | margin: 1em 0 1em 0; 184 | padding: 0.4em; 185 | } 186 | 187 | /* -- general body styles --------------------------------------------------- */ 188 | 189 | a.headerlink { 190 | visibility: hidden; 191 | } 192 | 193 | h1:hover > a.headerlink, 194 | h2:hover > a.headerlink, 195 | h3:hover > a.headerlink, 196 | h4:hover > a.headerlink, 197 | h5:hover > a.headerlink, 198 | h6:hover > a.headerlink, 199 | dt:hover > a.headerlink { 200 | visibility: visible; 201 | } 202 | 203 | div.body p.caption { 204 | text-align: inherit; 205 | } 206 | 207 | div.body td { 208 | text-align: left; 209 | } 210 | 211 | .field-list ul { 212 | padding-left: 1em; 213 | } 214 | 215 | .first { 216 | margin-top: 0 !important; 217 | } 218 | 219 | p.rubric { 220 | margin-top: 30px; 221 | font-weight: bold; 222 | } 223 | 224 | img.align-left, .figure.align-left, object.align-left { 225 | clear: left; 226 | float: left; 227 | margin-right: 1em; 228 | } 229 | 230 | img.align-right, .figure.align-right, object.align-right { 231 | clear: right; 232 | float: right; 233 | margin-left: 1em; 234 | } 235 | 236 | img.align-center, .figure.align-center, object.align-center { 237 | display: block; 238 | margin-left: auto; 239 | margin-right: auto; 240 | } 241 | 242 | .align-left { 243 | text-align: left; 244 | } 245 | 246 | .align-center { 247 | text-align: center; 248 | } 249 | 250 | .align-right { 251 | text-align: right; 252 | } 253 | 254 | /* -- sidebars -------------------------------------------------------------- */ 255 | 256 | div.sidebar { 257 | margin: 0 0 0.5em 1em; 258 | border: 1px solid #ddb; 259 | padding: 7px 7px 0 7px; 260 | background-color: #ffe; 261 | width: 40%; 262 | float: right; 263 | } 264 | 265 | p.sidebar-title { 266 | font-weight: bold; 267 | } 268 | 269 | /* -- topics ---------------------------------------------------------------- */ 270 | 271 | div.topic { 272 | border: 1px solid #ccc; 273 | padding: 7px 7px 0 7px; 274 | margin: 10px 0 10px 0; 275 | } 276 | 277 | p.topic-title { 278 | font-size: 1.1em; 279 | font-weight: bold; 280 | margin-top: 10px; 281 | } 282 | 283 | /* -- admonitions ----------------------------------------------------------- */ 284 | 285 | div.admonition { 286 | margin-top: 10px; 287 | margin-bottom: 10px; 288 | padding: 7px; 289 | } 290 | 291 | div.admonition dt { 292 | font-weight: bold; 293 | } 294 | 295 | div.admonition dl { 296 | margin-bottom: 0; 297 | } 298 | 299 | p.admonition-title { 300 | margin: 0px 10px 5px 0px; 301 | font-weight: bold; 302 | } 303 | 304 | div.body p.centered { 305 | text-align: center; 306 | margin-top: 25px; 307 | } 308 | 309 | /* -- tables ---------------------------------------------------------------- */ 310 | 311 | table.docutils { 312 | border: 0; 313 | border-collapse: collapse; 314 | } 315 | 316 | table.docutils td, table.docutils th { 317 | padding: 1px 8px 1px 5px; 318 | border-top: 0; 319 | border-left: 0; 320 | border-right: 0; 321 | border-bottom: 1px solid #aaa; 322 | } 323 | 324 | table.field-list td, table.field-list th { 325 | border: 0 !important; 326 | } 327 | 328 | table.footnote td, table.footnote th { 329 | border: 0 !important; 330 | } 331 | 332 | th { 333 | text-align: left; 334 | padding-right: 5px; 335 | } 336 | 337 | table.citation { 338 | border-left: solid 1px gray; 339 | margin-left: 1px; 340 | } 341 | 342 | table.citation td { 343 | border-bottom: none; 344 | } 345 | 346 | /* -- other body styles ----------------------------------------------------- */ 347 | 348 | ol.arabic { 349 | list-style: decimal; 350 | } 351 | 352 | ol.loweralpha { 353 | list-style: lower-alpha; 354 | } 355 | 356 | ol.upperalpha { 357 | list-style: upper-alpha; 358 | } 359 | 360 | ol.lowerroman { 361 | list-style: lower-roman; 362 | } 363 | 364 | ol.upperroman { 365 | list-style: upper-roman; 366 | } 367 | 368 | dl { 369 | margin-bottom: 15px; 370 | } 371 | 372 | dd p { 373 | margin-top: 0px; 374 | } 375 | 376 | dd ul, dd table { 377 | margin-bottom: 10px; 378 | } 379 | 380 | dd { 381 | margin-top: 3px; 382 | margin-bottom: 10px; 383 | margin-left: 30px; 384 | } 385 | 386 | dt:target, .highlighted { 387 | background-color: #fbe54e; 388 | } 389 | 390 | dl.glossary dt { 391 | font-weight: bold; 392 | font-size: 1.1em; 393 | } 394 | 395 | .field-list ul { 396 | margin: 0; 397 | padding-left: 1em; 398 | } 399 | 400 | .field-list p { 401 | margin: 0; 402 | } 403 | 404 | .refcount { 405 | color: #060; 406 | } 407 | 408 | .optional { 409 | font-size: 1.3em; 410 | } 411 | 412 | .versionmodified { 413 | font-style: italic; 414 | } 415 | 416 | .system-message { 417 | background-color: #fda; 418 | padding: 5px; 419 | border: 3px solid red; 420 | } 421 | 422 | .footnote:target { 423 | background-color: #ffa; 424 | } 425 | 426 | .line-block { 427 | display: block; 428 | margin-top: 1em; 429 | margin-bottom: 1em; 430 | } 431 | 432 | .line-block .line-block { 433 | margin-top: 0; 434 | margin-bottom: 0; 435 | margin-left: 1.5em; 436 | } 437 | 438 | .guilabel, .menuselection { 439 | font-family: sans-serif; 440 | } 441 | 442 | .accelerator { 443 | text-decoration: underline; 444 | } 445 | 446 | .classifier { 447 | font-style: oblique; 448 | } 449 | 450 | abbr, acronym { 451 | border-bottom: dotted 1px; 452 | cursor: help; 453 | } 454 | 455 | /* -- code displays --------------------------------------------------------- */ 456 | 457 | pre { 458 | overflow: auto; 459 | overflow-y: hidden; /* fixes display issues on Chrome browsers */ 460 | } 461 | 462 | td.linenos pre { 463 | padding: 5px 0px; 464 | border: 0; 465 | background-color: transparent; 466 | color: #aaa; 467 | } 468 | 469 | table.highlighttable { 470 | margin-left: 0.5em; 471 | } 472 | 473 | table.highlighttable td { 474 | padding: 0 0.5em 0 0.5em; 475 | } 476 | 477 | tt.descname { 478 | background-color: transparent; 479 | font-weight: bold; 480 | font-size: 1.2em; 481 | } 482 | 483 | tt.descclassname { 484 | background-color: transparent; 485 | } 486 | 487 | tt.xref, a tt { 488 | background-color: transparent; 489 | font-weight: bold; 490 | } 491 | 492 | h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt { 493 | background-color: transparent; 494 | } 495 | 496 | .viewcode-link { 497 | float: right; 498 | } 499 | 500 | .viewcode-back { 501 | float: right; 502 | font-family: sans-serif; 503 | } 504 | 505 | div.viewcode-block:target { 506 | margin: -1px -10px; 507 | padding: 0 10px; 508 | } 509 | 510 | /* -- math display ---------------------------------------------------------- */ 511 | 512 | img.math { 513 | vertical-align: middle; 514 | } 515 | 516 | div.body div.math p { 517 | text-align: center; 518 | } 519 | 520 | span.eqno { 521 | float: right; 522 | } 523 | 524 | /* -- printout stylesheet --------------------------------------------------- */ 525 | 526 | @media print { 527 | div.document, 528 | div.documentwrapper, 529 | div.bodywrapper { 530 | margin: 0 !important; 531 | width: 100%; 532 | } 533 | 534 | div.sphinxsidebar, 535 | div.related, 536 | div.footer, 537 | #top-link { 538 | display: none; 539 | } 540 | } -------------------------------------------------------------------------------- /docs/_build/html/_static/classic.css: -------------------------------------------------------------------------------- 1 | /* 2 | * default.css_t 3 | * ~~~~~~~~~~~~~ 4 | * 5 | * Sphinx stylesheet -- default theme. 6 | * 7 | * :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | @import url("basic.css"); 13 | 14 | /* -- page layout ----------------------------------------------------------- */ 15 | 16 | body { 17 | font-family: sans-serif; 18 | font-size: 100%; 19 | background-color: #11303d; 20 | color: #000; 21 | margin: 0; 22 | padding: 0; 23 | } 24 | 25 | div.document { 26 | background-color: #1c4e63; 27 | } 28 | 29 | div.documentwrapper { 30 | float: left; 31 | width: 100%; 32 | } 33 | 34 | div.bodywrapper { 35 | margin: 0 0 0 230px; 36 | } 37 | 38 | div.body { 39 | background-color: #ffffff; 40 | color: #000000; 41 | padding: 0 20px 30px 20px; 42 | } 43 | 44 | div.footer { 45 | color: #ffffff; 46 | width: 100%; 47 | padding: 9px 0 9px 0; 48 | text-align: center; 49 | font-size: 75%; 50 | } 51 | 52 | div.footer a { 53 | color: #ffffff; 54 | text-decoration: underline; 55 | } 56 | 57 | div.related { 58 | background-color: #133f52; 59 | line-height: 30px; 60 | color: #ffffff; 61 | } 62 | 63 | div.related a { 64 | color: #ffffff; 65 | } 66 | 67 | div.sphinxsidebar { 68 | } 69 | 70 | div.sphinxsidebar h3 { 71 | font-family: 'Trebuchet MS', sans-serif; 72 | color: #ffffff; 73 | font-size: 1.4em; 74 | font-weight: normal; 75 | margin: 0; 76 | padding: 0; 77 | } 78 | 79 | div.sphinxsidebar h3 a { 80 | color: #ffffff; 81 | } 82 | 83 | div.sphinxsidebar h4 { 84 | font-family: 'Trebuchet MS', sans-serif; 85 | color: #ffffff; 86 | font-size: 1.3em; 87 | font-weight: normal; 88 | margin: 5px 0 0 0; 89 | padding: 0; 90 | } 91 | 92 | div.sphinxsidebar p { 93 | color: #ffffff; 94 | } 95 | 96 | div.sphinxsidebar p.topless { 97 | margin: 5px 10px 10px 10px; 98 | } 99 | 100 | div.sphinxsidebar ul { 101 | margin: 10px; 102 | padding: 0; 103 | color: #ffffff; 104 | } 105 | 106 | div.sphinxsidebar a { 107 | color: #98dbcc; 108 | } 109 | 110 | div.sphinxsidebar input { 111 | border: 1px solid #98dbcc; 112 | font-family: sans-serif; 113 | font-size: 1em; 114 | } 115 | 116 | 117 | 118 | /* -- hyperlink styles ------------------------------------------------------ */ 119 | 120 | a { 121 | color: #355f7c; 122 | text-decoration: none; 123 | } 124 | 125 | a:visited { 126 | color: #355f7c; 127 | text-decoration: none; 128 | } 129 | 130 | a:hover { 131 | text-decoration: underline; 132 | } 133 | 134 | 135 | 136 | /* -- body styles ----------------------------------------------------------- */ 137 | 138 | div.body h1, 139 | div.body h2, 140 | div.body h3, 141 | div.body h4, 142 | div.body h5, 143 | div.body h6 { 144 | font-family: 'Trebuchet MS', sans-serif; 145 | background-color: #f2f2f2; 146 | font-weight: normal; 147 | color: #20435c; 148 | border-bottom: 1px solid #ccc; 149 | margin: 20px -20px 10px -20px; 150 | padding: 3px 0 3px 10px; 151 | } 152 | 153 | div.body h1 { margin-top: 0; font-size: 200%; } 154 | div.body h2 { font-size: 160%; } 155 | div.body h3 { font-size: 140%; } 156 | div.body h4 { font-size: 120%; } 157 | div.body h5 { font-size: 110%; } 158 | div.body h6 { font-size: 100%; } 159 | 160 | a.headerlink { 161 | color: #c60f0f; 162 | font-size: 0.8em; 163 | padding: 0 4px 0 4px; 164 | text-decoration: none; 165 | } 166 | 167 | a.headerlink:hover { 168 | background-color: #c60f0f; 169 | color: white; 170 | } 171 | 172 | div.body p, div.body dd, div.body li { 173 | text-align: justify; 174 | line-height: 130%; 175 | } 176 | 177 | div.admonition p.admonition-title + p { 178 | display: inline; 179 | } 180 | 181 | div.admonition p { 182 | margin-bottom: 5px; 183 | } 184 | 185 | div.admonition pre { 186 | margin-bottom: 5px; 187 | } 188 | 189 | div.admonition ul, div.admonition ol { 190 | margin-bottom: 5px; 191 | } 192 | 193 | div.note { 194 | background-color: #eee; 195 | border: 1px solid #ccc; 196 | } 197 | 198 | div.seealso { 199 | background-color: #ffc; 200 | border: 1px solid #ff6; 201 | } 202 | 203 | div.topic { 204 | background-color: #eee; 205 | } 206 | 207 | div.warning { 208 | background-color: #ffe4e4; 209 | border: 1px solid #f66; 210 | } 211 | 212 | p.admonition-title { 213 | display: inline; 214 | } 215 | 216 | p.admonition-title:after { 217 | content: ":"; 218 | } 219 | 220 | pre { 221 | padding: 5px; 222 | background-color: #eeffcc; 223 | color: #333333; 224 | line-height: 120%; 225 | border: 1px solid #ac9; 226 | border-left: none; 227 | border-right: none; 228 | } 229 | 230 | code { 231 | background-color: #ecf0f3; 232 | padding: 0 1px 0 1px; 233 | font-size: 0.95em; 234 | } 235 | 236 | th { 237 | background-color: #ede; 238 | } 239 | 240 | .warning code { 241 | background: #efc2c2; 242 | } 243 | 244 | .note code { 245 | background: #d6d6d6; 246 | } 247 | 248 | .viewcode-back { 249 | font-family: sans-serif; 250 | } 251 | 252 | div.viewcode-block:target { 253 | background-color: #f4debf; 254 | border-top: 1px solid #ac9; 255 | border-bottom: 1px solid #ac9; 256 | } 257 | 258 | div.code-block-caption { 259 | color: #efefef; 260 | background-color: #1c4e63; 261 | } -------------------------------------------------------------------------------- /docs/_build/html/_static/comment-bright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salesforce/LinuxTelemetry/37027505489f2719070c98320f5805ceda3b0824/docs/_build/html/_static/comment-bright.png -------------------------------------------------------------------------------- /docs/_build/html/_static/comment-close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salesforce/LinuxTelemetry/37027505489f2719070c98320f5805ceda3b0824/docs/_build/html/_static/comment-close.png -------------------------------------------------------------------------------- /docs/_build/html/_static/comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salesforce/LinuxTelemetry/37027505489f2719070c98320f5805ceda3b0824/docs/_build/html/_static/comment.png -------------------------------------------------------------------------------- /docs/_build/html/_static/default.css: -------------------------------------------------------------------------------- 1 | /* 2 | * default.css_t 3 | * ~~~~~~~~~~~~~ 4 | * 5 | * Sphinx stylesheet -- default theme. 6 | * 7 | * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | @import url("basic.css"); 13 | 14 | /* -- page layout ----------------------------------------------------------- */ 15 | 16 | body { 17 | font-family: sans-serif; 18 | font-size: 100%; 19 | background-color: #11303d; 20 | color: #000; 21 | margin: 0; 22 | padding: 0; 23 | } 24 | 25 | div.document { 26 | background-color: #1c4e63; 27 | } 28 | 29 | div.documentwrapper { 30 | float: left; 31 | width: 100%; 32 | } 33 | 34 | div.bodywrapper { 35 | margin: 0 0 0 230px; 36 | } 37 | 38 | div.body { 39 | background-color: #ffffff; 40 | color: #000000; 41 | padding: 0 20px 30px 20px; 42 | } 43 | 44 | div.footer { 45 | color: #ffffff; 46 | width: 100%; 47 | padding: 9px 0 9px 0; 48 | text-align: center; 49 | font-size: 75%; 50 | } 51 | 52 | div.footer a { 53 | color: #ffffff; 54 | text-decoration: underline; 55 | } 56 | 57 | div.related { 58 | background-color: #133f52; 59 | line-height: 30px; 60 | color: #ffffff; 61 | } 62 | 63 | div.related a { 64 | color: #ffffff; 65 | } 66 | 67 | div.sphinxsidebar { 68 | } 69 | 70 | div.sphinxsidebar h3 { 71 | font-family: 'Trebuchet MS', sans-serif; 72 | color: #ffffff; 73 | font-size: 1.4em; 74 | font-weight: normal; 75 | margin: 0; 76 | padding: 0; 77 | } 78 | 79 | div.sphinxsidebar h3 a { 80 | color: #ffffff; 81 | } 82 | 83 | div.sphinxsidebar h4 { 84 | font-family: 'Trebuchet MS', sans-serif; 85 | color: #ffffff; 86 | font-size: 1.3em; 87 | font-weight: normal; 88 | margin: 5px 0 0 0; 89 | padding: 0; 90 | } 91 | 92 | div.sphinxsidebar p { 93 | color: #ffffff; 94 | } 95 | 96 | div.sphinxsidebar p.topless { 97 | margin: 5px 10px 10px 10px; 98 | } 99 | 100 | div.sphinxsidebar ul { 101 | margin: 10px; 102 | padding: 0; 103 | color: #ffffff; 104 | } 105 | 106 | div.sphinxsidebar a { 107 | color: #98dbcc; 108 | } 109 | 110 | div.sphinxsidebar input { 111 | border: 1px solid #98dbcc; 112 | font-family: sans-serif; 113 | font-size: 1em; 114 | } 115 | 116 | 117 | 118 | /* -- hyperlink styles ------------------------------------------------------ */ 119 | 120 | a { 121 | color: #355f7c; 122 | text-decoration: none; 123 | } 124 | 125 | a:visited { 126 | color: #355f7c; 127 | text-decoration: none; 128 | } 129 | 130 | a:hover { 131 | text-decoration: underline; 132 | } 133 | 134 | 135 | 136 | /* -- body styles ----------------------------------------------------------- */ 137 | 138 | div.body h1, 139 | div.body h2, 140 | div.body h3, 141 | div.body h4, 142 | div.body h5, 143 | div.body h6 { 144 | font-family: 'Trebuchet MS', sans-serif; 145 | background-color: #f2f2f2; 146 | font-weight: normal; 147 | color: #20435c; 148 | border-bottom: 1px solid #ccc; 149 | margin: 20px -20px 10px -20px; 150 | padding: 3px 0 3px 10px; 151 | } 152 | 153 | div.body h1 { margin-top: 0; font-size: 200%; } 154 | div.body h2 { font-size: 160%; } 155 | div.body h3 { font-size: 140%; } 156 | div.body h4 { font-size: 120%; } 157 | div.body h5 { font-size: 110%; } 158 | div.body h6 { font-size: 100%; } 159 | 160 | a.headerlink { 161 | color: #c60f0f; 162 | font-size: 0.8em; 163 | padding: 0 4px 0 4px; 164 | text-decoration: none; 165 | } 166 | 167 | a.headerlink:hover { 168 | background-color: #c60f0f; 169 | color: white; 170 | } 171 | 172 | div.body p, div.body dd, div.body li { 173 | text-align: justify; 174 | line-height: 130%; 175 | } 176 | 177 | div.admonition p.admonition-title + p { 178 | display: inline; 179 | } 180 | 181 | div.admonition p { 182 | margin-bottom: 5px; 183 | } 184 | 185 | div.admonition pre { 186 | margin-bottom: 5px; 187 | } 188 | 189 | div.admonition ul, div.admonition ol { 190 | margin-bottom: 5px; 191 | } 192 | 193 | div.note { 194 | background-color: #eee; 195 | border: 1px solid #ccc; 196 | } 197 | 198 | div.seealso { 199 | background-color: #ffc; 200 | border: 1px solid #ff6; 201 | } 202 | 203 | div.topic { 204 | background-color: #eee; 205 | } 206 | 207 | div.warning { 208 | background-color: #ffe4e4; 209 | border: 1px solid #f66; 210 | } 211 | 212 | p.admonition-title { 213 | display: inline; 214 | } 215 | 216 | p.admonition-title:after { 217 | content: ":"; 218 | } 219 | 220 | pre { 221 | padding: 5px; 222 | background-color: #eeffcc; 223 | color: #333333; 224 | line-height: 120%; 225 | border: 1px solid #ac9; 226 | border-left: none; 227 | border-right: none; 228 | } 229 | 230 | tt { 231 | background-color: #ecf0f3; 232 | padding: 0 1px 0 1px; 233 | font-size: 0.95em; 234 | } 235 | 236 | th { 237 | background-color: #ede; 238 | } 239 | 240 | .warning tt { 241 | background: #efc2c2; 242 | } 243 | 244 | .note tt { 245 | background: #d6d6d6; 246 | } 247 | 248 | .viewcode-back { 249 | font-family: sans-serif; 250 | } 251 | 252 | div.viewcode-block:target { 253 | background-color: #f4debf; 254 | border-top: 1px solid #ac9; 255 | border-bottom: 1px solid #ac9; 256 | } -------------------------------------------------------------------------------- /docs/_build/html/_static/doctools.js: -------------------------------------------------------------------------------- 1 | /* 2 | * doctools.js 3 | * ~~~~~~~~~~~ 4 | * 5 | * Sphinx JavaScript utilities for all documentation. 6 | * 7 | * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | /** 13 | * select a different prefix for underscore 14 | */ 15 | $u = _.noConflict(); 16 | 17 | /** 18 | * make the code below compatible with browsers without 19 | * an installed firebug like debugger 20 | if (!window.console || !console.firebug) { 21 | var names = ["log", "debug", "info", "warn", "error", "assert", "dir", 22 | "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", 23 | "profile", "profileEnd"]; 24 | window.console = {}; 25 | for (var i = 0; i < names.length; ++i) 26 | window.console[names[i]] = function() {}; 27 | } 28 | */ 29 | 30 | /** 31 | * small helper function to urldecode strings 32 | */ 33 | jQuery.urldecode = function(x) { 34 | return decodeURIComponent(x).replace(/\+/g, ' '); 35 | } 36 | 37 | /** 38 | * small helper function to urlencode strings 39 | */ 40 | jQuery.urlencode = encodeURIComponent; 41 | 42 | /** 43 | * This function returns the parsed url parameters of the 44 | * current request. Multiple values per key are supported, 45 | * it will always return arrays of strings for the value parts. 46 | */ 47 | jQuery.getQueryParameters = function(s) { 48 | if (typeof s == 'undefined') 49 | s = document.location.search; 50 | var parts = s.substr(s.indexOf('?') + 1).split('&'); 51 | var result = {}; 52 | for (var i = 0; i < parts.length; i++) { 53 | var tmp = parts[i].split('=', 2); 54 | var key = jQuery.urldecode(tmp[0]); 55 | var value = jQuery.urldecode(tmp[1]); 56 | if (key in result) 57 | result[key].push(value); 58 | else 59 | result[key] = [value]; 60 | } 61 | return result; 62 | }; 63 | 64 | /** 65 | * small function to check if an array contains 66 | * a given item. 67 | */ 68 | jQuery.contains = function(arr, item) { 69 | for (var i = 0; i < arr.length; i++) { 70 | if (arr[i] == item) 71 | return true; 72 | } 73 | return false; 74 | }; 75 | 76 | /** 77 | * highlight a given string on a jquery object by wrapping it in 78 | * span elements with the given class name. 79 | */ 80 | jQuery.fn.highlightText = function(text, className) { 81 | function highlight(node) { 82 | if (node.nodeType == 3) { 83 | var val = node.nodeValue; 84 | var pos = val.toLowerCase().indexOf(text); 85 | if (pos >= 0 && !jQuery(node.parentNode).hasClass(className)) { 86 | var span = document.createElement("span"); 87 | span.className = className; 88 | span.appendChild(document.createTextNode(val.substr(pos, text.length))); 89 | node.parentNode.insertBefore(span, node.parentNode.insertBefore( 90 | document.createTextNode(val.substr(pos + text.length)), 91 | node.nextSibling)); 92 | node.nodeValue = val.substr(0, pos); 93 | } 94 | } 95 | else if (!jQuery(node).is("button, select, textarea")) { 96 | jQuery.each(node.childNodes, function() { 97 | highlight(this); 98 | }); 99 | } 100 | } 101 | return this.each(function() { 102 | highlight(this); 103 | }); 104 | }; 105 | 106 | /** 107 | * Small JavaScript module for the documentation. 108 | */ 109 | var Documentation = { 110 | 111 | init : function() { 112 | this.fixFirefoxAnchorBug(); 113 | this.highlightSearchWords(); 114 | this.initIndexTable(); 115 | }, 116 | 117 | /** 118 | * i18n support 119 | */ 120 | TRANSLATIONS : {}, 121 | PLURAL_EXPR : function(n) { return n == 1 ? 0 : 1; }, 122 | LOCALE : 'unknown', 123 | 124 | // gettext and ngettext don't access this so that the functions 125 | // can safely bound to a different name (_ = Documentation.gettext) 126 | gettext : function(string) { 127 | var translated = Documentation.TRANSLATIONS[string]; 128 | if (typeof translated == 'undefined') 129 | return string; 130 | return (typeof translated == 'string') ? translated : translated[0]; 131 | }, 132 | 133 | ngettext : function(singular, plural, n) { 134 | var translated = Documentation.TRANSLATIONS[singular]; 135 | if (typeof translated == 'undefined') 136 | return (n == 1) ? singular : plural; 137 | return translated[Documentation.PLURALEXPR(n)]; 138 | }, 139 | 140 | addTranslations : function(catalog) { 141 | for (var key in catalog.messages) 142 | this.TRANSLATIONS[key] = catalog.messages[key]; 143 | this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); 144 | this.LOCALE = catalog.locale; 145 | }, 146 | 147 | /** 148 | * add context elements like header anchor links 149 | */ 150 | addContextElements : function() { 151 | $('div[id] > :header:first').each(function() { 152 | $('\u00B6'). 153 | attr('href', '#' + this.id). 154 | attr('title', _('Permalink to this headline')). 155 | appendTo(this); 156 | }); 157 | $('dt[id]').each(function() { 158 | $('\u00B6'). 159 | attr('href', '#' + this.id). 160 | attr('title', _('Permalink to this definition')). 161 | appendTo(this); 162 | }); 163 | }, 164 | 165 | /** 166 | * workaround a firefox stupidity 167 | */ 168 | fixFirefoxAnchorBug : function() { 169 | if (document.location.hash && $.browser.mozilla) 170 | window.setTimeout(function() { 171 | document.location.href += ''; 172 | }, 10); 173 | }, 174 | 175 | /** 176 | * highlight the search words provided in the url in the text 177 | */ 178 | highlightSearchWords : function() { 179 | var params = $.getQueryParameters(); 180 | var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; 181 | if (terms.length) { 182 | var body = $('div.body'); 183 | window.setTimeout(function() { 184 | $.each(terms, function() { 185 | body.highlightText(this.toLowerCase(), 'highlighted'); 186 | }); 187 | }, 10); 188 | $('') 190 | .appendTo($('#searchbox')); 191 | } 192 | }, 193 | 194 | /** 195 | * init the domain index toggle buttons 196 | */ 197 | initIndexTable : function() { 198 | var togglers = $('img.toggler').click(function() { 199 | var src = $(this).attr('src'); 200 | var idnum = $(this).attr('id').substr(7); 201 | $('tr.cg-' + idnum).toggle(); 202 | if (src.substr(-9) == 'minus.png') 203 | $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); 204 | else 205 | $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); 206 | }).css('display', ''); 207 | if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { 208 | togglers.click(); 209 | } 210 | }, 211 | 212 | /** 213 | * helper function to hide the search marks again 214 | */ 215 | hideSearchWords : function() { 216 | $('#searchbox .highlight-link').fadeOut(300); 217 | $('span.highlighted').removeClass('highlighted'); 218 | }, 219 | 220 | /** 221 | * make the url absolute 222 | */ 223 | makeURL : function(relativeURL) { 224 | return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; 225 | }, 226 | 227 | /** 228 | * get the current relative url 229 | */ 230 | getCurrentURL : function() { 231 | var path = document.location.pathname; 232 | var parts = path.split(/\//); 233 | $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { 234 | if (this == '..') 235 | parts.pop(); 236 | }); 237 | var url = parts.join('/'); 238 | return path.substring(url.lastIndexOf('/') + 1, path.length - 1); 239 | } 240 | }; 241 | 242 | // quick alias for translations 243 | _ = Documentation.gettext; 244 | 245 | $(document).ready(function() { 246 | Documentation.init(); 247 | }); 248 | -------------------------------------------------------------------------------- /docs/_build/html/_static/down-pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salesforce/LinuxTelemetry/37027505489f2719070c98320f5805ceda3b0824/docs/_build/html/_static/down-pressed.png -------------------------------------------------------------------------------- /docs/_build/html/_static/down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salesforce/LinuxTelemetry/37027505489f2719070c98320f5805ceda3b0824/docs/_build/html/_static/down.png -------------------------------------------------------------------------------- /docs/_build/html/_static/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salesforce/LinuxTelemetry/37027505489f2719070c98320f5805ceda3b0824/docs/_build/html/_static/file.png -------------------------------------------------------------------------------- /docs/_build/html/_static/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salesforce/LinuxTelemetry/37027505489f2719070c98320f5805ceda3b0824/docs/_build/html/_static/minus.png -------------------------------------------------------------------------------- /docs/_build/html/_static/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salesforce/LinuxTelemetry/37027505489f2719070c98320f5805ceda3b0824/docs/_build/html/_static/plus.png -------------------------------------------------------------------------------- /docs/_build/html/_static/pygments.css: -------------------------------------------------------------------------------- 1 | .highlight .hll { background-color: #ffffcc } 2 | .highlight { background: #eeffcc; } 3 | .highlight .c { color: #408090; font-style: italic } /* Comment */ 4 | .highlight .err { border: 1px solid #FF0000 } /* Error */ 5 | .highlight .k { color: #007020; font-weight: bold } /* Keyword */ 6 | .highlight .o { color: #666666 } /* Operator */ 7 | .highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */ 8 | .highlight .cp { color: #007020 } /* Comment.Preproc */ 9 | .highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */ 10 | .highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */ 11 | .highlight .gd { color: #A00000 } /* Generic.Deleted */ 12 | .highlight .ge { font-style: italic } /* Generic.Emph */ 13 | .highlight .gr { color: #FF0000 } /* Generic.Error */ 14 | .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ 15 | .highlight .gi { color: #00A000 } /* Generic.Inserted */ 16 | .highlight .go { color: #303030 } /* Generic.Output */ 17 | .highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ 18 | .highlight .gs { font-weight: bold } /* Generic.Strong */ 19 | .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ 20 | .highlight .gt { color: #0040D0 } /* Generic.Traceback */ 21 | .highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ 22 | .highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ 23 | .highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ 24 | .highlight .kp { color: #007020 } /* Keyword.Pseudo */ 25 | .highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ 26 | .highlight .kt { color: #902000 } /* Keyword.Type */ 27 | .highlight .m { color: #208050 } /* Literal.Number */ 28 | .highlight .s { color: #4070a0 } /* Literal.String */ 29 | .highlight .na { color: #4070a0 } /* Name.Attribute */ 30 | .highlight .nb { color: #007020 } /* Name.Builtin */ 31 | .highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ 32 | .highlight .no { color: #60add5 } /* Name.Constant */ 33 | .highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */ 34 | .highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */ 35 | .highlight .ne { color: #007020 } /* Name.Exception */ 36 | .highlight .nf { color: #06287e } /* Name.Function */ 37 | .highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ 38 | .highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ 39 | .highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ 40 | .highlight .nv { color: #bb60d5 } /* Name.Variable */ 41 | .highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ 42 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */ 43 | .highlight .mf { color: #208050 } /* Literal.Number.Float */ 44 | .highlight .mh { color: #208050 } /* Literal.Number.Hex */ 45 | .highlight .mi { color: #208050 } /* Literal.Number.Integer */ 46 | .highlight .mo { color: #208050 } /* Literal.Number.Oct */ 47 | .highlight .sb { color: #4070a0 } /* Literal.String.Backtick */ 48 | .highlight .sc { color: #4070a0 } /* Literal.String.Char */ 49 | .highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ 50 | .highlight .s2 { color: #4070a0 } /* Literal.String.Double */ 51 | .highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ 52 | .highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */ 53 | .highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ 54 | .highlight .sx { color: #c65d09 } /* Literal.String.Other */ 55 | .highlight .sr { color: #235388 } /* Literal.String.Regex */ 56 | .highlight .s1 { color: #4070a0 } /* Literal.String.Single */ 57 | .highlight .ss { color: #517918 } /* Literal.String.Symbol */ 58 | .highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ 59 | .highlight .vc { color: #bb60d5 } /* Name.Variable.Class */ 60 | .highlight .vg { color: #bb60d5 } /* Name.Variable.Global */ 61 | .highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */ 62 | .highlight .il { color: #208050 } /* Literal.Number.Integer.Long */ -------------------------------------------------------------------------------- /docs/_build/html/_static/sidebar.js: -------------------------------------------------------------------------------- 1 | /* 2 | * sidebar.js 3 | * ~~~~~~~~~~ 4 | * 5 | * This script makes the Sphinx sidebar collapsible. 6 | * 7 | * .sphinxsidebar contains .sphinxsidebarwrapper. This script adds 8 | * in .sphixsidebar, after .sphinxsidebarwrapper, the #sidebarbutton 9 | * used to collapse and expand the sidebar. 10 | * 11 | * When the sidebar is collapsed the .sphinxsidebarwrapper is hidden 12 | * and the width of the sidebar and the margin-left of the document 13 | * are decreased. When the sidebar is expanded the opposite happens. 14 | * This script saves a per-browser/per-session cookie used to 15 | * remember the position of the sidebar among the pages. 16 | * Once the browser is closed the cookie is deleted and the position 17 | * reset to the default (expanded). 18 | * 19 | * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. 20 | * :license: BSD, see LICENSE for details. 21 | * 22 | */ 23 | 24 | $(function() { 25 | // global elements used by the functions. 26 | // the 'sidebarbutton' element is defined as global after its 27 | // creation, in the add_sidebar_button function 28 | var bodywrapper = $('.bodywrapper'); 29 | var sidebar = $('.sphinxsidebar'); 30 | var sidebarwrapper = $('.sphinxsidebarwrapper'); 31 | 32 | // for some reason, the document has no sidebar; do not run into errors 33 | if (!sidebar.length) return; 34 | 35 | // original margin-left of the bodywrapper and width of the sidebar 36 | // with the sidebar expanded 37 | var bw_margin_expanded = bodywrapper.css('margin-left'); 38 | var ssb_width_expanded = sidebar.width(); 39 | 40 | // margin-left of the bodywrapper and width of the sidebar 41 | // with the sidebar collapsed 42 | var bw_margin_collapsed = '.8em'; 43 | var ssb_width_collapsed = '.8em'; 44 | 45 | // colors used by the current theme 46 | var dark_color = $('.related').css('background-color'); 47 | var light_color = $('.document').css('background-color'); 48 | 49 | function sidebar_is_collapsed() { 50 | return sidebarwrapper.is(':not(:visible)'); 51 | } 52 | 53 | function toggle_sidebar() { 54 | if (sidebar_is_collapsed()) 55 | expand_sidebar(); 56 | else 57 | collapse_sidebar(); 58 | } 59 | 60 | function collapse_sidebar() { 61 | sidebarwrapper.hide(); 62 | sidebar.css('width', ssb_width_collapsed); 63 | bodywrapper.css('margin-left', bw_margin_collapsed); 64 | sidebarbutton.css({ 65 | 'margin-left': '0', 66 | 'height': bodywrapper.height() 67 | }); 68 | sidebarbutton.find('span').text('»'); 69 | sidebarbutton.attr('title', _('Expand sidebar')); 70 | document.cookie = 'sidebar=collapsed'; 71 | } 72 | 73 | function expand_sidebar() { 74 | bodywrapper.css('margin-left', bw_margin_expanded); 75 | sidebar.css('width', ssb_width_expanded); 76 | sidebarwrapper.show(); 77 | sidebarbutton.css({ 78 | 'margin-left': ssb_width_expanded-12, 79 | 'height': bodywrapper.height() 80 | }); 81 | sidebarbutton.find('span').text('«'); 82 | sidebarbutton.attr('title', _('Collapse sidebar')); 83 | document.cookie = 'sidebar=expanded'; 84 | } 85 | 86 | function add_sidebar_button() { 87 | sidebarwrapper.css({ 88 | 'float': 'left', 89 | 'margin-right': '0', 90 | 'width': ssb_width_expanded - 28 91 | }); 92 | // create the button 93 | sidebar.append( 94 | '
«
' 95 | ); 96 | var sidebarbutton = $('#sidebarbutton'); 97 | light_color = sidebarbutton.css('background-color'); 98 | // find the height of the viewport to center the '<<' in the page 99 | var viewport_height; 100 | if (window.innerHeight) 101 | viewport_height = window.innerHeight; 102 | else 103 | viewport_height = $(window).height(); 104 | sidebarbutton.find('span').css({ 105 | 'display': 'block', 106 | 'margin-top': (viewport_height - sidebar.position().top - 20) / 2 107 | }); 108 | 109 | sidebarbutton.click(toggle_sidebar); 110 | sidebarbutton.attr('title', _('Collapse sidebar')); 111 | sidebarbutton.css({ 112 | 'color': '#FFFFFF', 113 | 'border-left': '1px solid ' + dark_color, 114 | 'font-size': '1.2em', 115 | 'cursor': 'pointer', 116 | 'height': bodywrapper.height(), 117 | 'padding-top': '1px', 118 | 'margin-left': ssb_width_expanded - 12 119 | }); 120 | 121 | sidebarbutton.hover( 122 | function () { 123 | $(this).css('background-color', dark_color); 124 | }, 125 | function () { 126 | $(this).css('background-color', light_color); 127 | } 128 | ); 129 | } 130 | 131 | function set_position_from_cookie() { 132 | if (!document.cookie) 133 | return; 134 | var items = document.cookie.split(';'); 135 | for(var k=0; k 5 | 6 | 7 | 8 | 9 | 10 | 11 | buddyinfo Module — LinuxTelemetry 1 documentation 12 | 13 | 14 | 15 | 16 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 51 | 52 |
53 |
54 |
55 |
56 | 57 |
58 |

buddyinfo Module

59 |

buddyinfo.py

60 |

Linux uses buddy allocator for memory management. Pages 61 | are allocated in each NUMA node and zones within each 62 | node. Within each zones, pages are allocated as 63 | contiguous groups of 1, 2, 3, 4, and so on order 64 | pages where 1 means 4K pages. Number of free pages in 65 | each bucket is exposed through /proc/buddyinfo 66 | When this number goes below a threshold in any bucket, 67 | kswapd (slowpath for finding free pages) kicks in. It 68 | then scans for free pages in all order levels until 69 | all of them reach above min limit. This process can take 70 | long time and may cause issues for GC latencies.

71 |

Typical contents of /proc/buddyinfo:

72 |
    73 |
  • Node 0, zone Normal 1490 4026 12224 8508 4493 1929 849 301 101 45 5257
  • 74 |
  • Node 1, zone DMA 1 1 1 1 1 0 1 0 1 1 3
  • 75 |
  • Node 1, zone DMA32 15 3 2 5 8 7 4 4 7 8 681
  • 76 |
  • Node 1, zone Normal 6061 13681 20887 15188 9097 4546 1948 731 273 125 3976
  • 77 |
78 |

Here are the fields interpretation in each row: 79 | 1. NUMA node (such as 0 or 1) 80 | 2. Zone name (Normal, DMA32, DMA, etc.) 81 | 3. Col. 3 to end: page order or buckets on contiguous memory sizes: 4K, 8K, 16K, 32K, 64K, 128K, 256K, 512K, 1024K, and 2048K

82 |
83 |
84 | buddyinfo.collect_buddyinfo()[source]
85 |
86 | 87 |
88 |
89 | buddyinfo.configer(ObjConfiguration)[source]
90 |
91 | 92 |
93 |
94 | buddyinfo.get_host_type()[source]
95 |
96 | 97 |
98 |
99 | buddyinfo.init_stats_cache()[source]
100 |
101 | 102 |
103 |
104 | buddyinfo.initer()[source]
105 |
106 | 107 |
108 |
109 | buddyinfo.reader(input_data=None)[source]
110 |
111 | 112 |
113 |
114 | buddyinfo.shutdown()[source]
115 |
116 | 117 |
118 |
119 | buddyinfo.swap_current_cache()[source]
120 |
121 | 122 |
123 |
124 | buddyinfo.writer(metric, data=None)[source]
125 |
126 | 127 |
128 | 129 | 130 |
131 |
132 |
133 |
134 |
135 |

Previous topic

136 |

Welcome to LinuxTelemetry’s documentation!

138 |

Next topic

139 |

diskstats Module

141 |

This Page

142 | 146 | 158 | 159 |
160 |
161 |
162 |
163 | 181 | 185 | 186 | -------------------------------------------------------------------------------- /docs/_build/html/fusionio.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | fusionio Module — LinuxTelemetry 1 documentation 12 | 13 | 14 | 15 | 16 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 51 | 52 |
53 |
54 |
55 |
56 | 57 |
58 |

fusionio Module

59 |

fusionio.py

60 |

Collectd plugin for fusion-io device measurement. It 61 | currently measures: 62 | 1. physical blocks read 63 | 2. physical blocks written 64 | 3. total blocks 65 | 4. min block erases count 66 | 5. max block erases count 67 | 6. average block erases count

68 |
69 |

physical bytes written are obtained as:

70 |

cmd_bytes_written = ‘/usr/bin/fio-status -a | ‘

71 |

cmd_bytes_written += ‘grep “Physical bytes written:” | ‘

72 |

cmd_bytes_written += ‘awk ‘{print $4}’‘

73 |
74 |
75 |

physical bytes read are obtained as:

76 |

cmd_bytes_read = ‘/usr/bin/fio-status -a | ‘

77 |

cmd_bytes_read += ‘grep “Physical bytes read :” | ‘

78 |

cmd_bytes_read += ‘awk ‘{print $5}’‘

79 |
80 |
81 |

Block erase counts (total, min, max, avg) are obtained as:

82 |

cmd_erased_blocks = ‘/usr/bin/fio-get-erase-count /dev/fct0 | ‘

83 |

cmd_erased_blocks += ‘tail -n 5 | cut -d: -f 2 | sed ‘s/^ *//’‘

84 |
85 |
86 | fusionio.collect_fiostats()[source]
87 |
88 | 89 |
90 |
91 | fusionio.configer(ObjConfiguration)[source]
92 |
93 | 94 |
95 |
96 | fusionio.extract_val(out, key)[source]
97 |
98 | 99 |
100 |
101 | fusionio.get_block_erases()[source]
102 |
103 | 104 |
105 |
106 | fusionio.get_fiostats()[source]
107 |
108 | 109 |
110 |
111 | fusionio.get_host_type()[source]
112 |
113 | 114 |
115 |
116 | fusionio.get_physical_bytes()[source]
117 |
118 | 119 |
120 |
121 | fusionio.grep(s, pattern)[source]
122 |
123 | 124 |
125 |
126 | fusionio.init_stats_cache()[source]
127 |
128 | 129 |
130 |
131 | fusionio.initer()[source]
132 |
133 | 134 |
135 |
136 | fusionio.is_fio_device()[source]
137 |
138 | 139 |
140 |
141 | fusionio.reader(input_data=None)[source]
142 |
143 | 144 |
145 |
146 | fusionio.remove_start(s, word_to_remove)[source]
147 |
148 | 149 |
150 |
151 | fusionio.run_cmd(cmd)[source]
152 |
153 | 154 |
155 |
156 | fusionio.shutdown()[source]
157 |
158 | 159 |
160 |
161 | fusionio.swap_current_cache()[source]
162 |
163 | 164 |
165 |
166 | fusionio.writer(metric, data=None)[source]
167 |
168 | 169 |
170 |
171 | 172 | 173 |
174 |
175 |
176 |
177 |
178 |

Table Of Contents

179 | 187 | 188 |

Previous topic

189 |

diskstats Module

191 |

Next topic

192 |

netstats Module

194 |

This Page

195 | 199 | 211 | 212 |
213 |
214 |
215 |
216 | 234 | 238 | 239 | -------------------------------------------------------------------------------- /docs/_build/html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Welcome to LinuxTelemetry’s documentation! — LinuxTelemetry 1 documentation 12 | 13 | 14 | 15 | 16 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 47 | 48 |
49 |
50 |
51 |
52 | 53 |
54 |

Welcome to LinuxTelemetry’s documentation!

55 |

Linux procfs maintains a large number of system metrics that are used for monitoring and debugging system health and performance. We have developed a number of collectd plugins to capture metrics related to memory, storage devices, and networking protocols. Continuous collection of these metrics is critical for cloud infrastructure monitoring, tuning, capacity planning, and analytics

56 |

Contents:

57 | 80 |
81 |
82 |

Indices and tables

83 | 88 |
89 | 90 | 91 |
92 |
93 |
94 |
95 |
96 |

Table Of Contents

97 | 103 | 104 |

Next topic

105 |

buddyinfo Module

107 |

This Page

108 | 112 | 124 | 125 |
126 |
127 |
128 |
129 | 144 | 148 | 149 | -------------------------------------------------------------------------------- /docs/_build/html/objects.inv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salesforce/LinuxTelemetry/37027505489f2719070c98320f5805ceda3b0824/docs/_build/html/objects.inv -------------------------------------------------------------------------------- /docs/_build/html/py-modindex.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Python Module Index — LinuxTelemetry 1 documentation 12 | 13 | 14 | 15 | 16 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 34 | 35 | 36 | 37 | 38 | 50 | 51 |
52 |
53 |
54 |
55 | 56 | 57 |

Python Module Index

58 | 59 |
60 | b | 61 | d | 62 | f | 63 | n | 64 | v | 65 | z 66 |
67 | 68 | 69 | 70 | 72 | 73 | 74 | 77 | 78 | 80 | 81 | 82 | 85 | 86 | 88 | 89 | 90 | 93 | 94 | 96 | 97 | 98 | 101 | 102 | 104 | 105 | 106 | 109 | 110 | 112 | 113 | 114 | 117 |
 
71 | b
75 | buddyinfo 76 |
 
79 | d
83 | diskstats 84 |
 
87 | f
91 | fusionio 92 |
 
95 | n
99 | netstats 100 |
 
103 | v
107 | vmstats 108 |
 
111 | z
115 | zoneinfo 116 |
118 | 119 | 120 |
121 |
122 |
123 |
124 |
125 | 137 | 138 |
139 |
140 |
141 |
142 | 154 | 158 | 159 | -------------------------------------------------------------------------------- /docs/_build/html/search.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Search — LinuxTelemetry 1 documentation 12 | 13 | 14 | 15 | 16 | 25 | 26 | 27 | 28 | 29 | 30 | 33 | 34 | 35 | 36 | 37 | 49 | 50 |
51 |
52 |
53 |
54 | 55 |

Search

56 |
57 | 58 |

59 | Please activate JavaScript to enable the search 60 | functionality. 61 |

62 |
63 |

64 | From here you can search these documents. Enter your search 65 | words into the box below and click "search". Note that the search 66 | function will automatically search for all of the words. Pages 67 | containing fewer words won't appear in the result list. 68 |

69 |
70 | 71 | 72 | 73 |
74 | 75 |
76 | 77 |
78 | 79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 | 100 | 104 | 105 | -------------------------------------------------------------------------------- /docs/_build/html/searchindex.js: -------------------------------------------------------------------------------- 1 | Search.setIndex({objects:{"":{zoneinfo:[1,0,1,""],vmstats:[2,0,1,""],buddyinfo:[3,0,1,""],diskstats:[4,0,1,""],fusionio:[5,0,1,""],netstats:[6,0,1,""]},zoneinfo:{initer:[1,1,1,""],collect_zoneinfo:[1,1,1,""],swap_current_cache:[1,1,1,""],writer:[1,1,1,""],init_stats_cache:[1,1,1,""],shutdown:[1,1,1,""],reader:[1,1,1,""],get_host_type:[1,1,1,""],configer:[1,1,1,""]},vmstats:{initer:[2,1,1,""],shutdown:[2,1,1,""],dispatch_metrics:[2,1,1,""],swap_current_cache:[2,1,1,""],writer:[2,1,1,""],init_stats_cache:[2,1,1,""],calc_vmstats:[2,1,1,""],calc_vmstats_rate:[2,1,1,""],reader:[2,1,1,""],get_host_type:[2,1,1,""],configer:[2,1,1,""],collect_vmstats:[2,1,1,""]},buddyinfo:{initer:[3,1,1,""],collect_buddyinfo:[3,1,1,""],swap_current_cache:[3,1,1,""],writer:[3,1,1,""],init_stats_cache:[3,1,1,""],shutdown:[3,1,1,""],reader:[3,1,1,""],get_host_type:[3,1,1,""],configer:[3,1,1,""]},diskstats:{initer:[4,1,1,""],dispatch_metrics:[4,1,1,""],swap_current_cache:[4,1,1,""],writer:[4,1,1,""],calc_del_t:[4,1,1,""],get_dev_list:[4,1,1,""],init_dev_stats_cache:[4,1,1,""],shutdown:[4,1,1,""],reader:[4,1,1,""],METRIC_TYPE:[4,2,1,""],configer:[4,1,1,""],calc_metrics:[4,1,1,""],collect_diskstats:[4,1,1,""]},fusionio:{initer:[5,1,1,""],get_physical_bytes:[5,1,1,""],get_fiostats:[5,1,1,""],swap_current_cache:[5,1,1,""],writer:[5,1,1,""],run_cmd:[5,1,1,""],init_stats_cache:[5,1,1,""],reader:[5,1,1,""],get_host_type:[5,1,1,""],is_fio_device:[5,1,1,""],shutdown:[5,1,1,""],remove_start:[5,1,1,""],extract_val:[5,1,1,""],grep:[5,1,1,""],collect_fiostats:[5,1,1,""],configer:[5,1,1,""],get_block_erases:[5,1,1,""]},netstats:{init_netstat_counters_list:[6,1,1,""],init_counters_list:[6,1,1,""],initer:[6,1,1,""],dispatch_metrics:[6,1,1,""],writer:[6,1,1,""],get_matches:[6,1,1,""],collect_netstats:[6,1,1,""],init_snmp_counters_list:[6,1,1,""],shutdown:[6,1,1,""],reader:[6,1,1,""],get_host_type:[6,1,1,""],configer:[6,1,1,""]}},terms:{all:[6,3,4],compact_fail:2,skip:4,global:4,unevictable_pgs_rescu:2,supplement:1,follow:2,disk:[2,4],row:3,millisecond:4,decid:4,zone:[1,2,3],nr_anon_transparent_hugepag:2,passiveopen:6,diskstat:[0,4],send:6,init:[1,2,3,4,5,6],buddi:3,"256k":3,rto:6,sent:6,get_match:6,passiv:6,pawsestab:6,sourc:[1,2,3,4,5,6],everi:2,inparmprob:6,reader:[1,2,3,4,5,6],tcpabortondata:6,theread:2,util:4,outoctet:6,get_dev_list:4,pgscan_direct_mov:2,level:3,cmd:5,list:[6,2,4],calc_vmstats_r:2,cooki:6,diskstats_dev_too_mani:4,nr_page_table_pag:2,direct:2,pgrefill_norm:2,zero:[2,4],further:6,port:6,index:0,end_that_request_last:4,collect_diskstat:4,sub:[6,4],repli:6,pgscan_kswapd_dma32:2,"while":6,find:3,pgsteal_mov:2,dma32:3,net:6,attemptfail:6,deriv:4,intrest:2,twrecycl:6,gener:2,here:3,satisfi:2,let:4,address:6,remove_start:5,delayedacklock:6,becom:4,sinc:4,interpret:3,wait:6,search:0,outrst:6,queue:6,nr_writeback:2,multicast:6,nr_slab_reclaim:2,pagecach:2,typic:[6,3],reclaim:2,"1024k":3,tcpext:[0,6],ofoprun:6,rcvbuferror:6,md2:4,calc_metr:4,decrement:4,total:[5,0,6,2,4],establish:6,md0:4,unit:4,from:[6,2,4],memori:[0,1,2,3],activeopen:6,tail:[5,2],next:4,predict:6,usr:5,get_host_typ:[5,1,2,6,3],until:3,minor:2,unevictable_pgs_scan:2,get_fiostat:5,relat:0,line:4,"2048k":3,reasmreqd:6,examin:6,tcptimeout:6,destin:6,cach:[2,4],overrun:6,none:[1,2,3,4,5,6],cmd_bytes_written:5,inmsg:6,dev:[5,4],can:[2,3,4],tcpdirectcopyfrombacklog:6,indatagram:6,collect_fiostat:5,cmd_erased_block:5,scan:[2,3],process:3,lock:6,indic:0,fusionio:[5,0],critic:0,abort:6,want:4,recycl:6,calc_vmstat:2,delai:6,end:3,dsack:6,listendrop:6,write:4,how:4,reject:6,delayedack:6,config:[1,2,3,4,5,6],"128k":3,updat:4,max:[5,0,6],calc_del_t:4,compact_blocks_mov:2,wrong:6,pgscan_kswapd_norm:2,numa:[1,3],mai:[3,4],data:[1,2,3,4,5,6],averag:5,alloc:3,attempt:6,outtimestamprep:6,counter:6,outerror:6,pgalloc_dma32:2,issu:3,perform:0,pgscan_kswapd_mov:2,block:[5,0,2],order:[6,3],init_netstat_counters_list:6,inerror:6,becaus:[6,2],retransseg:6,increas:4,through:[6,3],htlb_buddy_alloc_fail:2,vari:2,paramet:6,kswapd_steal:2,group:3,monitor:[0,4],outmsg:6,ipext:[0,6],window:6,infrastructur:0,fio:[5,4],them:[6,3],"return":4,thei:[6,4],fragment:6,timestamp:[6,4],overal:4,handi:4,number:[0,2,3,4],"break":1,pgrefill_dma32:2,echo:6,outaddrmaskrep:6,nr_isolated_fil:2,name:[6,3],compact_stal:2,tcpabortontimeout:6,drop:6,mode:6,timeout:6,each:[1,3,4],debug:0,done:4,mean:[6,3,4],weight:4,pgalloc_dma:2,continu:0,request_queu:4,connect:6,beyond:4,event:6,out:[5,6,2],merg:4,rex:6,inmcastoctet:6,network:[0,6],contigu:3,goe:3,publish:6,content:[0,3],health:0,pgactiv:2,print:5,pgscan_direct_dma32:2,occurr:2,difficulti:2,inerr:6,tcplossfailur:6,reasmfail:6,kilobyt:2,netstat:[0,6],free:[2,3],quick:6,base:[2,4],sdb:4,dictionari:4,outdestunreach:6,md3:4,"byte":[5,0,2],md1:4,recv:6,pginodest:2,pgsteal_dma32:2,nr_writeback_temp:2,timer:6,length:4,rcvprune:6,place:2,pawsact:6,first:4,size:3,major:2,directli:[6,2],nr_file_pag:2,buddyinfo:[0,1,3],capac:0,set:[6,4],pgscank:2,pgscan:2,metric_typ:4,pgscand:2,open:6,objconfigur:[1,2,3,4,5,6],fct0:5,given:4,"long":[3,4],nr_inactive_anon:2,unknown:6,system:[0,2],messag:6,unevictable_pgs_clear:2,too:2,nr_anon_pag:2,udp:[0,6],tool:6,nr_mlock:2,broadcast:6,part:6,collectd:[5,0,4],than:2,nr_free_pag:2,grep:5,prune:6,provid:[1,2,4],second:2,numa_interleav:2,were:6,nr_active_anon:2,listen:6,outtimeexcd:6,seri:4,outparmprob:6,quench:6,syncookiess:6,ram:4,ani:3,linuxtelemetri:0,have:[0,2],tabl:0,need:4,sar:2,maxconn:6,caus:3,inecho:6,min:[5,0,6,3],currestab:6,note:2,also:4,maintain:0,take:3,which:[6,2,4],outredirect:6,kswapd:[2,3],nr_inactive_fil:2,normal:3,track:4,reach:3,embryonicrst:6,awk:5,plan:0,indeliv:6,tcpabortonclos:6,segment:6,"32k":3,request:[6,4],determin:4,numa_hit:2,"64k":3,sda:4,sector:4,outrequest:6,pkt:6,show:4,outmcastpkt:6,syncookiesrecv:6,slabs_scan:2,pgfault:2,threshold:3,nr_map:2,redirect:6,current:[5,4],onli:[6,2,4],slow:6,kswapd_inodest:2,explain:4,writer:[1,2,3,4,5,6],activ:6,pgmajfault:2,should:4,unevictable_pgs_munlock:2,latenc:3,queu:[6,4],cmd_bytes_read:5,tune:0,analyt:0,count:[5,0,2,4],swapcach:2,get:[5,2],outofwindowicmp:6,inaddrmaskrep:6,report:2,compact_pages_mov:2,requir:[6,2],inhdrerror:6,lockdroppedicmp:6,kswapd_low_wmark_hit_quickli:2,whether:4,bad:6,insrcquench:6,statist:[2,4],partit:4,fname:6,gaug:4,where:3,kernel:[2,4],unevictable_pgs_mlock:2,dev_list:4,inmcastpkt:6,iostat:4,listenoverflow:6,packet:6,sed:5,arg:4,fail:6,close:6,estabreset:6,tcppureack:6,statu:5,estab:6,sndbuferror:6,pattern:5,zoneinfo:[0,1],label:6,written:[5,0,4],is_fio_devic:5,progress:4,kei:[5,4],pgpgin:2,come:2,addit:4,both:4,procf:0,last:4,expos:[6,3],plugin:[0,1,2,4,5,6],fault:2,syncookiesfail:6,numa_loc:2,etc:[3,4],befor:4,"__make_request":4,delayedacklost:6,logic:4,pawspass:6,tcpprequeu:6,white_list:6,col:3,load:2,rtoalgorithm:6,"16k":3,period:2,run_cmd:5,header:6,shutdown:[1,2,3,4,5,6],linux:[0,6,3,4],respect:1,ultim:4,stamp:6,init_counters_list:6,devic:[5,0,4],due:6,been:2,outmcastoctet:6,syn_recv:6,valu:[2,4],pgsteal:2,outaddrmask:6,outnorout:6,inoctet:6,kswapd_skip_congestion_wait:2,intimeexcd:6,demand:2,prequeu:6,those:2,outtimestamp:6,tcpprequeuedrop:6,look:4,raw:4,calcul:2,nr_unstabl:2,abov:3,error:6,loop:4,bin:5,increment:4,dropped_aft:6,almost:2,metric:[0,1,2,3,4,5,6],deliv:6,non:4,pgrotat:2,physic:[5,0],indestunreach:6,eras:[5,0],pgrefill_dma:2,incom:6,avg:[5,0],pgscan_direct_dma:2,pgscan_kswapd_dma:2,develop:0,welcom:0,unevictable_pgs_mlockfre:2,receiv:6,pswpin:2,init_dev_stats_cach:4,recvmsg:6,contain:6,kswapd_high_wmark_hit_quickli:2,pgrefill_mov:2,nr_kernel_stack:2,document:[0,4],get_physical_byt:5,complet:4,exhaust:6,finish:[6,4],zone_reclaim_fail:2,syn:6,iop:4,tcphphitstous:6,user:6,transit:6,slowpath:3,reassembl:6,reclam:2,inredirect:6,retransmiss:6,appropri:4,off:2,unevictable_pgs_cul:2,certian:4,thu:4,spent:4,nr_shmem:2,without:2,command:6,thi:[6,2,3,4],rtomax:6,protocol:[0,6],less:2,inbcastoctet:6,tcp:[0,6],inrec:6,invalid:6,outechorep:6,kilo:2,inaddrmask:6,compact_success:2,pswpout:2,cut:5,struct:4,easi:4,nr_active_fil:2,numa_miss:2,input:6,modul:[0,1,2,3,4,5,6],kick:3,earli:6,htlb_buddy_alloc_success:2,collect_zoneinfo:1,read:[5,0,6,4],forwdatagram:6,fusion:5,know:4,reap:2,loss:6,daemon:2,like:4,specif:4,indiscard:6,resolv:2,collect:[0,4],output:[2,4],manag:3,backlog:[6,4],outecho:6,tcpdirectcopyfromprequeu:6,exceed:6,old:[6,2],retransmit:6,"512k":3,pgsteal_dma:2,acknowledg:6,interv:[2,4],some:2,twkill:6,numa_foreign:2,inact:2,successfulli:4,nonzero:4,pgsteal_norm:2,txt:4,octet:6,per:[2,4],nr_isolated_anon:2,buffer:6,pgpgout:2,larg:[0,4],init_snmp_counters_list:6,proc:[1,2,6,3,4],run:2,outsrcquench:6,obtain:[5,0],dev_nam:4,inbcastpkt:6,post:2,diskstats_dev_limit:4,plug:4,intimestamp:6,socket:6,ack:6,pgalloc_mov:2,page:[0,2,3],input_data:[1,2,3,4,5,6],nr_vmscan_writ:2,includ:4,intimestamprep:6,discard:6,embryon:6,get_block_eras:5,majflt:2,soc:6,effici:[2,4],proto:6,unreach:6,within:3,compact_pagemigrate_fail:2,two:4,down:1,outseg:6,storag:[0,4],often:4,val:[6,4],accumul:4,prunecal:6,support:4,captur:0,snmp:6,fast:6,avail:[6,2],start:4,inechorep:6,low:2,forward:6,outdatagram:6,collect_netstat:6,"function":4,unexpect:6,nr_slab_unreclaim:2,nr_dirti:2,cloud:0,measur:[5,1,4],nr_bounc:2,inclu:4,overflow:6,icmp:[0,6],buf:6,reset:6,dma:3,made:2,consist:2,possibl:4,extract_v:5,bucket:3,displai:2,asynchron:2,below:[2,3],limit:[3,4],hand:4,noport:6,numa_oth:2,tcphphit:6,dure:2,pageoutrun:2,constand:4,file:4,adjac:4,pgscan_direct_norm:2,collect_buddyinfo:3,when:[2,3,4],virtual:[1,2],dispatch_metr:[6,2,4],field:[2,3,4],other:4,you:4,unevictable_pgs_strand:2,reasmok:6,node:[1,3,4],stat:[1,4],pgdeactiv:2,rtomin:6,time:[6,2,3,4],collect_vmstat:2,nr_unevict:2,vmeff:2,allocstal:2,pgfree:2,inseg:6,init_stats_cach:[5,1,2,3],algorithm:6,tcpdsackolds:6,mask:6,swap_current_cach:[5,1,2,3,4],word_to_remov:5,vmstat:[0,1,2],ignor:[6,4],pgalloc_norm:2},objtypes:{"0":"py:module","1":"py:function","2":"py:data"},titles:["Welcome to LinuxTelemetry’s documentation!","zoneinfo Module","vmstats Module","buddyinfo Module","diskstats Module","fusionio Module","netstats Module"],objnames:{"0":["py","module","Python module"],"1":["py","function","Python function"],"2":["py","data","Python data"]},filenames:["index","zoneinfo","vmstats","buddyinfo","diskstats","fusionio","netstats"]}) -------------------------------------------------------------------------------- /docs/_build/html/zoneinfo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | zoneinfo Module — LinuxTelemetry 1 documentation 12 | 13 | 14 | 15 | 16 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 47 | 48 |
49 |
50 |
51 |
52 | 53 |
54 |

zoneinfo Module

55 |

zoneinfo.py

56 |

/proc/zoneinfo breaks down virtual memory stats with respect to each 57 | NUMA node and memory zone. It supplements the measurements 58 | provided by vmstats and buddyinfo plugins.

59 |
60 |
61 | zoneinfo.collect_zoneinfo()[source]
62 |
63 | 64 |
65 |
66 | zoneinfo.configer(ObjConfiguration)[source]
67 |
68 | 69 |
70 |
71 | zoneinfo.get_host_type()[source]
72 |
73 | 74 |
75 |
76 | zoneinfo.init_stats_cache()[source]
77 |
78 | 79 |
80 |
81 | zoneinfo.initer()[source]
82 |
83 | 84 |
85 |
86 | zoneinfo.reader(input_data=None)[source]
87 |
88 | 89 |
90 |
91 | zoneinfo.shutdown()[source]
92 |
93 | 94 |
95 |
96 | zoneinfo.swap_current_cache()[source]
97 |
98 | 99 |
100 |
101 | zoneinfo.writer(metric, data=None)[source]
102 |
103 | 104 |
105 | 106 | 107 |
108 |
109 |
110 |
111 |
112 |

Previous topic

113 |

vmstats Module

115 |

This Page

116 | 120 | 132 | 133 |
134 |
135 |
136 |
137 | 152 | 156 | 157 | -------------------------------------------------------------------------------- /docs/buddyinfo.rst: -------------------------------------------------------------------------------- 1 | buddyinfo Module 2 | ================ 3 | 4 | .. automodule:: buddyinfo 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # plugins documentation build configuration file, created by 4 | # sphinx-quickstart on Sat Jan 2 21:49:11 2016. 5 | # 6 | # This file is execfile()d with the current directory set to its containing dir. 7 | # 8 | # Note that not all possible configuration values are present in this 9 | # autogenerated file. 10 | # 11 | # All configuration values have a default; values that are commented out 12 | # serve to show the default. 13 | 14 | import sys, os 15 | 16 | # If extensions (or modules to document with autodoc) are in another directory, 17 | # add these directories to sys.path here. If the directory is relative to the 18 | # documentation root, use os.path.abspath to make it absolute, like shown here. 19 | sys.path.insert(0, os.path.abspath('/home/awaheed/ws/solrt/telemetry/plugins')) 20 | sys.path.insert(0, os.path.abspath('/home/awaheed/ws/solrt/telemetry/tests')) 21 | 22 | # -- General configuration ----------------------------------------------------- 23 | 24 | # If your documentation needs a minimal Sphinx version, state it here. 25 | #needs_sphinx = '1.0' 26 | 27 | # Add any Sphinx extension module names here, as strings. They can be extensions 28 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. 29 | extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode'] 30 | 31 | # Add any paths that contain templates here, relative to this directory. 32 | templates_path = ['_templates'] 33 | 34 | # The suffix of source filenames. 35 | source_suffix = '.rst' 36 | 37 | # The encoding of source files. 38 | #source_encoding = 'utf-8-sig' 39 | 40 | # The master toctree document. 41 | master_doc = 'index' 42 | 43 | # General information about the project. 44 | project = u'LinuxTelemetry' 45 | copyright = u'2016, Abdul Waheed' 46 | 47 | # The version info for the project you're documenting, acts as replacement for 48 | # |version| and |release|, also used in various other places throughout the 49 | # built documents. 50 | # 51 | # The short X.Y version. 52 | version = '0.3' 53 | # The full version, including alpha/beta/rc tags. 54 | release = '1' 55 | 56 | # The language for content autogenerated by Sphinx. Refer to documentation 57 | # for a list of supported languages. 58 | #language = None 59 | 60 | # There are two options for replacing |today|: either, you set today to some 61 | # non-false value, then it is used: 62 | #today = '' 63 | # Else, today_fmt is used as the format for a strftime call. 64 | #today_fmt = '%B %d, %Y' 65 | 66 | # List of patterns, relative to source directory, that match files and 67 | # directories to ignore when looking for source files. 68 | exclude_patterns = ['_build'] 69 | 70 | # The reST default role (used for this markup: `text`) to use for all documents. 71 | #default_role = None 72 | 73 | # If true, '()' will be appended to :func: etc. cross-reference text. 74 | #add_function_parentheses = True 75 | 76 | # If true, the current module name will be prepended to all description 77 | # unit titles (such as .. function::). 78 | #add_module_names = True 79 | 80 | # If true, sectionauthor and moduleauthor directives will be shown in the 81 | # output. They are ignored by default. 82 | #show_authors = False 83 | 84 | # The name of the Pygments (syntax highlighting) style to use. 85 | pygments_style = 'sphinx' 86 | 87 | # A list of ignored prefixes for module index sorting. 88 | #modindex_common_prefix = [] 89 | 90 | 91 | # -- Options for HTML output --------------------------------------------------- 92 | 93 | # The theme to use for HTML and HTML Help pages. See the documentation for 94 | # a list of builtin themes. 95 | html_theme = 'default' 96 | 97 | # Theme options are theme-specific and customize the look and feel of a theme 98 | # further. For a list of options available for each theme, see the 99 | # documentation. 100 | #html_theme_options = {} 101 | 102 | # Add any paths that contain custom themes here, relative to this directory. 103 | #html_theme_path = [] 104 | 105 | # The name for this set of Sphinx documents. If None, it defaults to 106 | # " v documentation". 107 | #html_title = None 108 | 109 | # A shorter title for the navigation bar. Default is the same as html_title. 110 | #html_short_title = None 111 | 112 | # The name of an image file (relative to this directory) to place at the top 113 | # of the sidebar. 114 | #html_logo = None 115 | 116 | # The name of an image file (within the static path) to use as favicon of the 117 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 118 | # pixels large. 119 | #html_favicon = None 120 | 121 | # Add any paths that contain custom static files (such as style sheets) here, 122 | # relative to this directory. They are copied after the builtin static files, 123 | # so a file named "default.css" will overwrite the builtin "default.css". 124 | html_static_path = ['_static'] 125 | 126 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 127 | # using the given strftime format. 128 | #html_last_updated_fmt = '%b %d, %Y' 129 | 130 | # If true, SmartyPants will be used to convert quotes and dashes to 131 | # typographically correct entities. 132 | #html_use_smartypants = True 133 | 134 | # Custom sidebar templates, maps document names to template names. 135 | #html_sidebars = {} 136 | 137 | # Additional templates that should be rendered to pages, maps page names to 138 | # template names. 139 | #html_additional_pages = {} 140 | 141 | # If false, no module index is generated. 142 | #html_domain_indices = True 143 | 144 | # If false, no index is generated. 145 | #html_use_index = True 146 | 147 | # If true, the index is split into individual pages for each letter. 148 | #html_split_index = False 149 | 150 | # If true, links to the reST sources are added to the pages. 151 | #html_show_sourcelink = True 152 | 153 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 154 | #html_show_sphinx = True 155 | 156 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 157 | #html_show_copyright = True 158 | 159 | # If true, an OpenSearch description file will be output, and all pages will 160 | # contain a tag referring to it. The value of this option must be the 161 | # base URL from which the finished HTML is served. 162 | #html_use_opensearch = '' 163 | 164 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 165 | #html_file_suffix = None 166 | 167 | # Output file base name for HTML help builder. 168 | htmlhelp_basename = 'pluginsdoc' 169 | 170 | 171 | # -- Options for LaTeX output -------------------------------------------------- 172 | 173 | latex_elements = { 174 | # The paper size ('letterpaper' or 'a4paper'). 175 | #'papersize': 'letterpaper', 176 | 177 | # The font size ('10pt', '11pt' or '12pt'). 178 | #'pointsize': '10pt', 179 | 180 | # Additional stuff for the LaTeX preamble. 181 | #'preamble': '', 182 | } 183 | 184 | # Grouping the document tree into LaTeX files. List of tuples 185 | # (source start file, target name, title, author, documentclass [howto/manual]). 186 | latex_documents = [ 187 | ('index', 'plugins.tex', u'plugins Documentation', 188 | u'Author', 'manual'), 189 | ] 190 | 191 | # The name of an image file (relative to this directory) to place at the top of 192 | # the title page. 193 | #latex_logo = None 194 | 195 | # For "manual" documents, if this is true, then toplevel headings are parts, 196 | # not chapters. 197 | #latex_use_parts = False 198 | 199 | # If true, show page references after internal links. 200 | #latex_show_pagerefs = False 201 | 202 | # If true, show URL addresses after external links. 203 | #latex_show_urls = False 204 | 205 | # Documents to append as an appendix to all manuals. 206 | #latex_appendices = [] 207 | 208 | # If false, no module index is generated. 209 | #latex_domain_indices = True 210 | 211 | 212 | # -- Options for manual page output -------------------------------------------- 213 | 214 | # One entry per manual page. List of tuples 215 | # (source start file, name, description, authors, manual section). 216 | man_pages = [ 217 | ('index', 'plugins', u'plugins Documentation', 218 | [u'Author'], 1) 219 | ] 220 | 221 | # If true, show URL addresses after external links. 222 | #man_show_urls = False 223 | 224 | 225 | # -- Options for Texinfo output ------------------------------------------------ 226 | 227 | # Grouping the document tree into Texinfo files. List of tuples 228 | # (source start file, target name, title, author, 229 | # dir menu entry, description, category) 230 | texinfo_documents = [ 231 | ('index', 'plugins', u'plugins Documentation', 232 | u'Author', 'plugins', 'One line description of project.', 233 | 'Miscellaneous'), 234 | ] 235 | 236 | # Documents to append as an appendix to all manuals. 237 | #texinfo_appendices = [] 238 | 239 | # If false, no module index is generated. 240 | #texinfo_domain_indices = True 241 | 242 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 243 | #texinfo_show_urls = 'footnote' 244 | 245 | 246 | # -- Options for Epub output --------------------------------------------------- 247 | 248 | # Bibliographic Dublin Core info. 249 | epub_title = u'plugins' 250 | epub_author = u'Author' 251 | epub_publisher = u'Author' 252 | epub_copyright = u'2016, Author' 253 | 254 | # The language of the text. It defaults to the language option 255 | # or en if the language is not set. 256 | #epub_language = '' 257 | 258 | # The scheme of the identifier. Typical schemes are ISBN or URL. 259 | #epub_scheme = '' 260 | 261 | # The unique identifier of the text. This can be a ISBN number 262 | # or the project homepage. 263 | #epub_identifier = '' 264 | 265 | # A unique identification for the text. 266 | #epub_uid = '' 267 | 268 | # A tuple containing the cover image and cover page html template filenames. 269 | #epub_cover = () 270 | 271 | # HTML files that should be inserted before the pages created by sphinx. 272 | # The format is a list of tuples containing the path and title. 273 | #epub_pre_files = [] 274 | 275 | # HTML files shat should be inserted after the pages created by sphinx. 276 | # The format is a list of tuples containing the path and title. 277 | #epub_post_files = [] 278 | 279 | # A list of files that should not be packed into the epub file. 280 | #epub_exclude_files = [] 281 | 282 | # The depth of the table of contents in toc.ncx. 283 | #epub_tocdepth = 3 284 | 285 | # Allow duplicate toc entries. 286 | #epub_tocdup = True 287 | -------------------------------------------------------------------------------- /docs/diskstats.rst: -------------------------------------------------------------------------------- 1 | diskstats Module 2 | ================ 3 | 4 | .. automodule:: diskstats 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/fusionio.rst: -------------------------------------------------------------------------------- 1 | fusionio Module 2 | =============== 3 | 4 | .. automodule:: fusionio 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. plugins documentation master file, created by 2 | sphinx-quickstart on Sat Jan 2 21:49:11 2016. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to LinuxTelemetry's documentation! 7 | ========================================== 8 | 9 | Linux procfs maintains a large number of system metrics that are used for monitoring and debugging system health and performance. We have developed a number of collectd plugins to capture metrics related to memory, storage devices, and networking protocols. Continuous collection of these metrics is critical for cloud infrastructure monitoring, tuning, capacity planning, and analytics 10 | 11 | Contents: 12 | 13 | .. toctree:: 14 | :maxdepth: 4 15 | 16 | buddyinfo 17 | diskstats 18 | fusionio 19 | netstats 20 | vmstats 21 | zoneinfo 22 | 23 | 24 | Indices and tables 25 | ================== 26 | 27 | * :ref:`genindex` 28 | * :ref:`modindex` 29 | * :ref:`search` 30 | 31 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM Command file for Sphinx documentation 4 | 5 | if "%SPHINXBUILD%" == "" ( 6 | set SPHINXBUILD=sphinx-build 7 | ) 8 | set BUILDDIR=_build 9 | set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . 10 | set I18NSPHINXOPTS=%SPHINXOPTS% . 11 | if NOT "%PAPER%" == "" ( 12 | set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% 13 | set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% 14 | ) 15 | 16 | if "%1" == "" goto help 17 | 18 | if "%1" == "help" ( 19 | :help 20 | echo.Please use `make ^` where ^ is one of 21 | echo. html to make standalone HTML files 22 | echo. dirhtml to make HTML files named index.html in directories 23 | echo. singlehtml to make a single large HTML file 24 | echo. pickle to make pickle files 25 | echo. json to make JSON files 26 | echo. htmlhelp to make HTML files and a HTML help project 27 | echo. qthelp to make HTML files and a qthelp project 28 | echo. devhelp to make HTML files and a Devhelp project 29 | echo. epub to make an epub 30 | echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter 31 | echo. text to make text files 32 | echo. man to make manual pages 33 | echo. texinfo to make Texinfo files 34 | echo. gettext to make PO message catalogs 35 | echo. changes to make an overview over all changed/added/deprecated items 36 | echo. linkcheck to check all external links for integrity 37 | echo. doctest to run all doctests embedded in the documentation if enabled 38 | goto end 39 | ) 40 | 41 | if "%1" == "clean" ( 42 | for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i 43 | del /q /s %BUILDDIR%\* 44 | goto end 45 | ) 46 | 47 | if "%1" == "html" ( 48 | %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html 49 | if errorlevel 1 exit /b 1 50 | echo. 51 | echo.Build finished. The HTML pages are in %BUILDDIR%/html. 52 | goto end 53 | ) 54 | 55 | if "%1" == "dirhtml" ( 56 | %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml 57 | if errorlevel 1 exit /b 1 58 | echo. 59 | echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. 60 | goto end 61 | ) 62 | 63 | if "%1" == "singlehtml" ( 64 | %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml 65 | if errorlevel 1 exit /b 1 66 | echo. 67 | echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. 68 | goto end 69 | ) 70 | 71 | if "%1" == "pickle" ( 72 | %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle 73 | if errorlevel 1 exit /b 1 74 | echo. 75 | echo.Build finished; now you can process the pickle files. 76 | goto end 77 | ) 78 | 79 | if "%1" == "json" ( 80 | %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json 81 | if errorlevel 1 exit /b 1 82 | echo. 83 | echo.Build finished; now you can process the JSON files. 84 | goto end 85 | ) 86 | 87 | if "%1" == "htmlhelp" ( 88 | %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp 89 | if errorlevel 1 exit /b 1 90 | echo. 91 | echo.Build finished; now you can run HTML Help Workshop with the ^ 92 | .hhp project file in %BUILDDIR%/htmlhelp. 93 | goto end 94 | ) 95 | 96 | if "%1" == "qthelp" ( 97 | %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp 98 | if errorlevel 1 exit /b 1 99 | echo. 100 | echo.Build finished; now you can run "qcollectiongenerator" with the ^ 101 | .qhcp project file in %BUILDDIR%/qthelp, like this: 102 | echo.^> qcollectiongenerator %BUILDDIR%\qthelp\plugins.qhcp 103 | echo.To view the help file: 104 | echo.^> assistant -collectionFile %BUILDDIR%\qthelp\plugins.ghc 105 | goto end 106 | ) 107 | 108 | if "%1" == "devhelp" ( 109 | %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp 110 | if errorlevel 1 exit /b 1 111 | echo. 112 | echo.Build finished. 113 | goto end 114 | ) 115 | 116 | if "%1" == "epub" ( 117 | %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub 118 | if errorlevel 1 exit /b 1 119 | echo. 120 | echo.Build finished. The epub file is in %BUILDDIR%/epub. 121 | goto end 122 | ) 123 | 124 | if "%1" == "latex" ( 125 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 126 | if errorlevel 1 exit /b 1 127 | echo. 128 | echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. 129 | goto end 130 | ) 131 | 132 | if "%1" == "text" ( 133 | %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text 134 | if errorlevel 1 exit /b 1 135 | echo. 136 | echo.Build finished. The text files are in %BUILDDIR%/text. 137 | goto end 138 | ) 139 | 140 | if "%1" == "man" ( 141 | %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man 142 | if errorlevel 1 exit /b 1 143 | echo. 144 | echo.Build finished. The manual pages are in %BUILDDIR%/man. 145 | goto end 146 | ) 147 | 148 | if "%1" == "texinfo" ( 149 | %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo 150 | if errorlevel 1 exit /b 1 151 | echo. 152 | echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. 153 | goto end 154 | ) 155 | 156 | if "%1" == "gettext" ( 157 | %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale 158 | if errorlevel 1 exit /b 1 159 | echo. 160 | echo.Build finished. The message catalogs are in %BUILDDIR%/locale. 161 | goto end 162 | ) 163 | 164 | if "%1" == "changes" ( 165 | %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes 166 | if errorlevel 1 exit /b 1 167 | echo. 168 | echo.The overview file is in %BUILDDIR%/changes. 169 | goto end 170 | ) 171 | 172 | if "%1" == "linkcheck" ( 173 | %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck 174 | if errorlevel 1 exit /b 1 175 | echo. 176 | echo.Link check complete; look for any errors in the above output ^ 177 | or in %BUILDDIR%/linkcheck/output.txt. 178 | goto end 179 | ) 180 | 181 | if "%1" == "doctest" ( 182 | %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest 183 | if errorlevel 1 exit /b 1 184 | echo. 185 | echo.Testing of doctests in the sources finished, look at the ^ 186 | results in %BUILDDIR%/doctest/output.txt. 187 | goto end 188 | ) 189 | 190 | :end 191 | -------------------------------------------------------------------------------- /docs/netstats.rst: -------------------------------------------------------------------------------- 1 | netstats Module 2 | =============== 3 | 4 | .. automodule:: netstats 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/vmstats.rst: -------------------------------------------------------------------------------- 1 | vmstats Module 2 | ============== 3 | 4 | .. automodule:: vmstats 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/zoneinfo.rst: -------------------------------------------------------------------------------- 1 | zoneinfo Module 2 | =============== 3 | 4 | .. automodule:: zoneinfo 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /plugins/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salesforce/LinuxTelemetry/37027505489f2719070c98320f5805ceda3b0824/plugins/__init__.py -------------------------------------------------------------------------------- /plugins/buddyinfo.conf: -------------------------------------------------------------------------------- 1 | 2 | Globals true 3 | 4 | 5 | 6 | ModulePath "/usr/share/collectd/plugins/python" 7 | LogTraces true 8 | Interactive false 9 | Import "buddyinfo" 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /plugins/buddyinfo.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | ########################################################################## 4 | # Copyright (c) 2015, Salesforce.com, Inc. 5 | # All rights reserved. 6 | # 7 | # Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # 10 | # Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer 12 | # in the documentation and/or other materials provided with the 13 | # distribution. 14 | # 15 | # Neither the name of Salesforce.com nor the names of its 16 | # contributors may be used to endorse or promote products 17 | # derived from this software without specific prior written permission. 18 | # 19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 21 | # NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23 | # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 24 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 26 | # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 28 | # IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 29 | # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 30 | # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | ########################################################################## 32 | 33 | """ 34 | **buddyinfo.py** 35 | 36 | Linux uses buddy allocator for memory management. Pages 37 | are allocated in each NUMA node and zones within each 38 | node. Within each zones, pages are allocated as 39 | contiguous groups of 1, 2, 3, 4, and so on order 40 | pages where 1 means 4K pages. Number of free pages in 41 | each bucket is exposed through /proc/buddyinfo 42 | When this number goes below a threshold in any bucket, 43 | kswapd (slowpath for finding free pages) kicks in. It 44 | then scans for free pages in all order levels until 45 | all of them reach above min limit. This process can take 46 | long time and may cause issues for GC latencies. 47 | 48 | Typical contents of /proc/buddyinfo: 49 | 50 | - Node 0, zone Normal 1490 4026 12224 8508 4493 1929 849 301 101 45 5257 51 | - Node 1, zone DMA 1 1 1 1 1 0 1 0 1 1 3 52 | - Node 1, zone DMA32 15 3 2 5 8 7 4 4 7 8 681 53 | - Node 1, zone Normal 6061 13681 20887 15188 9097 4546 1948 731 273 125 3976 54 | 55 | Here are the fields interpretation in each row: 56 | 1. NUMA node (such as 0 or 1) 57 | 2. Zone name (Normal, DMA32, DMA, etc.) 58 | 3. Col. 3 to end: page order or buckets on contiguous memory sizes: 4K, 8K, 16K, 32K, 64K, 128K, 256K, 512K, 1024K, and 2048K 59 | 60 | """ 61 | 62 | import collectd 63 | import platform 64 | import os 65 | import socket 66 | import time 67 | import re 68 | import sys 69 | import traceback 70 | 71 | os_name = platform.system() 72 | host_name = socket.gethostbyaddr(socket.gethostname())[0] 73 | host_types = ['app', 'db', 'ffx', 'indexer', 'search', 'other'] 74 | host_type = 'other' 75 | 76 | BUDDY_FNAME = '/proc/buddyinfo' 77 | METRIC_PLUGIN = 'buddyinfo' 78 | METRIC_TYPE = 'gauge' 79 | 80 | buddy_fields = ['numa_node', 81 | 'zone_name', 82 | 'bucket_free_pages' 83 | ] 84 | buddy_metrics = ['bucket_free_pages_per_sec', 85 | 'total_free_pages_per_sec', 86 | 'pct_fragment_per_sec' 87 | ] 88 | 89 | white_list = [] 90 | node_list = [] 91 | zone_list = [] 92 | 93 | stats_cache = {} 94 | stats_current = {} 95 | 96 | re_buddyinfo=re.compile(r'^\s*Node\s+(?P\d+)' 97 | r',\s+zone\s+(?P\S+)\s+(?P.*)$') 98 | 99 | def get_host_type(): 100 | for i in host_types: 101 | if i in host_name: 102 | host_type = i 103 | 104 | def init_stats_cache(): 105 | global white_list 106 | 107 | try: 108 | if os.path.exists(BUDDY_FNAME): 109 | num_buckets = 0 110 | with open(BUDDY_FNAME) as f: 111 | for line in f: 112 | match = re_buddyinfo.search(line) 113 | if not match: 114 | collectd.error('buddyinfo: unknown line pattern: %s' % (line)) 115 | continue; 116 | if 'node' in match.groupdict(): 117 | node = match.group('node') 118 | else: 119 | collectd.error('node not found in buddyinfo') 120 | return 121 | if 'zone' in match.groupdict(): 122 | zone = match.group('zone') 123 | else: 124 | collectd.error('zone not found in buddyinfo') 125 | return 126 | if 'pages' in match.groupdict(): 127 | free_pages = match.group('pages').strip().split() 128 | else: 129 | collectd.error('pages not found in buddyinfo') 130 | return 131 | num_buckets = len(free_pages) 132 | if node not in node_list: 133 | node_list.append(node) 134 | if zone not in zone_list: 135 | zone_list.append(zone) 136 | stats_cache[(node, zone, 'val')] = free_pages 137 | stats_cache[(node, zone, 'ts')] = time.time() 138 | f.close() 139 | for i in range(0, num_buckets): 140 | white_list.append('free_pages_' + str(4*2**i) + 'K') 141 | collectd.info('buddyinfo: node_list : %s' % (node_list)) 142 | collectd.info('buddyinfo: zone_list : %s' % (zone_list)) 143 | collectd.info('buddyinfo: white_list: %s' % (white_list)) 144 | else: 145 | collectd.info('buddyinfo: init_stats_cache: path: %s does not exist' 146 | % (BUDDY_FNAME)) 147 | except Exception as e: 148 | exc_type, exc_value, exc_traceback = sys.exc_info() 149 | collectd.error('Exception during buddyinfo init: %s\n%s' % 150 | (str(e), traceback.format_tb(exc_traceback))) 151 | 152 | def collect_buddyinfo(): 153 | try: 154 | if os.path.exists(BUDDY_FNAME): 155 | with open(BUDDY_FNAME) as f: 156 | for line in f: 157 | match = re_buddyinfo.search(line) 158 | if not match: 159 | continue; 160 | if 'node' in match.groupdict(): 161 | node = match.group('node') 162 | else: 163 | collectd.error('node not found in buddyinfo') 164 | return 165 | if 'zone' in match.groupdict(): 166 | zone = match.group('zone') 167 | else: 168 | collectd.error('zone not found in buddyinfo') 169 | return 170 | if 'pages' in match.groupdict(): 171 | free_pages = match.group('pages').strip().split() 172 | else: 173 | collectd.error('pages not found in buddyinfo') 174 | return 175 | stats_current[(node, zone, 'val')] = free_pages 176 | stats_current[(node, zone, 'ts')] = time.time() 177 | key_val = dict(zip(white_list, free_pages)) 178 | metric = collectd.Values() 179 | metric.host = host_name 180 | metric.plugin = METRIC_PLUGIN 181 | metric.plugin_instance = node 182 | metric.type = METRIC_TYPE 183 | for k in range(0, len(white_list)): 184 | metric.type_instance = 'zone_' + zone + '.' 185 | metric.type_instance += white_list[k] 186 | metric.values = [free_pages[k]] 187 | metric.dispatch() 188 | f.close() 189 | else: 190 | collectd.error('buddyinfo: procfs path: %s does not exist' 191 | % (BUDDY_FNAME)) 192 | except Exception as e: 193 | exc_type, exc_value, exc_traceback = sys.exc_info() 194 | collectd.error('Exception during buddyinfo collection: %s\n%s' % 195 | (str(e), traceback.format_tb(exc_traceback))) 196 | 197 | def swap_current_cache(): 198 | stats_cache = stats_current.copy() 199 | 200 | def configer(ObjConfiguration): 201 | collectd.info('buddyinfo plugin: configuring host: %s' % (host_name)) 202 | 203 | def initer(): 204 | get_host_type() 205 | collectd.info('buddyinfo plugin: host of type: %s' % (host_type)) 206 | collectd.info('buddyinfo initer: white list: %s' % (white_list)) 207 | init_stats_cache() 208 | collectd.info('buddyinfo init: stats_cache: %s' % (stats_cache)) 209 | 210 | def reader(input_data=None): 211 | collect_buddyinfo() 212 | swap_current_cache() 213 | 214 | def writer(metric, data=None): 215 | for i in metric.values: 216 | collectd.debug('%s (%s): %f' % (metric.plugin, metric.type, i)) 217 | 218 | def shutdown(): 219 | collectd.info('buddyinfo plugin shutting down') 220 | 221 | #== Callbacks ==# 222 | if (os_name == 'Linux'): 223 | collectd.register_config(configer) 224 | collectd.register_init(initer) 225 | collectd.register_read(reader) 226 | collectd.register_write(writer) 227 | collectd.register_shutdown(shutdown) 228 | else: 229 | collectd.warning('buddyinfo plugin currently works for Linux only') 230 | -------------------------------------------------------------------------------- /plugins/diskstats.conf: -------------------------------------------------------------------------------- 1 | 2 | Globals true 3 | 4 | 5 | 6 | ModulePath "/usr/share/collectd/plugins/python" 7 | LogTraces true 8 | Interactive false 9 | Import "diskstats" 10 | 11 | Verbose true 12 | DiskFilter "^sd[a-z]+$" "^sr0$" 13 | # DiskFilter "" 14 | Filter "iops_rw" "bytes_ps_rw" "bytes_per_rw" "util_pct" "avgqu_sz" "svc_tm" 15 | # Filter "" 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /plugins/fusionio.conf: -------------------------------------------------------------------------------- 1 | 2 | Globals true 3 | 4 | 5 | 6 | ModulePath "/usr/share/collectd/plugins/python" 7 | LogTraces true 8 | Interactive false 9 | Import "fusionio" 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /plugins/fusionio.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | ########################################################################## 4 | # Copyright (c) 2015, Salesforce.com, Inc. 5 | # All rights reserved. 6 | # 7 | # Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # 10 | # Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer 12 | # in the documentation and/or other materials provided with the 13 | # distribution. 14 | # 15 | # Neither the name of Salesforce.com nor the names of its 16 | # contributors may be used to endorse or promote products 17 | # derived from this software without specific prior written permission. 18 | # 19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 21 | # NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23 | # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 24 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 26 | # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 28 | # IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 29 | # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 30 | # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | ########################################################################## 32 | 33 | """ 34 | **fusionio.py** 35 | 36 | Collectd plugin for fusion-io device measurement. It 37 | currently measures: 38 | 1. physical blocks read 39 | 2. physical blocks written 40 | 3. total blocks 41 | 4. min block erases count 42 | 5. max block erases count 43 | 6. average block erases count 44 | 45 | physical bytes written are obtained as: 46 | --------------------------------------- 47 | 48 | cmd_bytes_written = '/usr/bin/fio-status -a | ' 49 | 50 | cmd_bytes_written += 'grep \"Physical bytes written:\" | ' 51 | 52 | cmd_bytes_written += 'awk \'{print $4}\'' 53 | 54 | physical bytes read are obtained as: 55 | ------------------------------------ 56 | 57 | cmd_bytes_read = '/usr/bin/fio-status -a | ' 58 | 59 | cmd_bytes_read += 'grep \"Physical bytes read :\" | ' 60 | 61 | cmd_bytes_read += 'awk \'{print $5}\'' 62 | 63 | Block erase counts (total, min, max, avg) are obtained as: 64 | ---------------------------------------------------------- 65 | 66 | cmd_erased_blocks = '/usr/bin/fio-get-erase-count /dev/fct0 | ' 67 | 68 | cmd_erased_blocks += 'tail -n 5 | cut -d: -f 2 | sed \'s/^ \*//\'' 69 | 70 | """ 71 | 72 | import collectd 73 | import platform 74 | import os 75 | import socket 76 | import time 77 | import re 78 | import subprocess 79 | 80 | try: 81 | long # Python 2 82 | except NameError: 83 | long = int # Python 3 84 | 85 | os_name = platform.system() 86 | host_name = socket.gethostbyaddr(socket.gethostname())[0] 87 | host_types = ['app', 'db', 'ffx', 'indexer', 'search', 'other'] 88 | host_type = 'other' 89 | 90 | cmd_fio_status = '/usr/bin/fio-status' 91 | args_fio_status = '-a' 92 | key_bytes_read = 'Physical bytes read :' 93 | key_bytes_written = 'Physical bytes written:' 94 | 95 | cmd_fio_get_erase_blocks = '/usr/bin/fio-get-erase-count' 96 | args_fio_get_erase_blocks = '-s /dev/fct0' 97 | key_blocks_total = 'Total blocks:' 98 | key_blocks_min = 'Min:' 99 | key_blocks_max = 'Max:' 100 | key_blocks_avg = 'Avg:' 101 | 102 | fio_fname = '/proc/fusion/fio/fioa/data/groomer/stats' 103 | fio_fields = ['Blocks'] 104 | #'Data copied:'] 105 | fio_white_list = ['phy_bytes_written', 106 | 'phy_bytes_read', 107 | 'erased_blocks_total', 108 | 'erased_blocks_min', 109 | 'erased_blocks_max', 110 | 'erased_blocks_avg'] 111 | 112 | fio_metrics = ['physical_bytes_read_per_sec', 113 | 'physical_bytes_written_per_sec', 114 | 'blocks_erased_per_sec'] 115 | 116 | stats_cache = {} 117 | stats_current = {} 118 | fiostats_cache = {} 119 | fiostats_current = {} 120 | 121 | def get_host_type(): 122 | global host_type 123 | for i in host_types: 124 | if i in host_name: 125 | host_type = i 126 | collectd.info('fusionio: get_host_by_type: %s' % (host_type)) 127 | 128 | def is_fio_device(): 129 | if os.path.exists(fio_fname): 130 | if os.path.exists(cmd_fio_status): 131 | if os.path.exists(cmd_fio_get_erase_blocks): 132 | return True 133 | else: 134 | collectd.error('%s not found:' % (cmd_fio_get_erase_blocks)) 135 | else: 136 | collectd.error('%s not found:' % (cmd_fio_status)) 137 | else: 138 | collectd.error('%s not found:' % (fio_fname)) 139 | 140 | return False 141 | 142 | def run_cmd (cmd): 143 | s = '' 144 | p = subprocess.Popen(cmd, 145 | shell=True, 146 | stdout=subprocess.PIPE, 147 | stderr=subprocess.STDOUT) 148 | for line in p.stdout.readlines(): 149 | s += line 150 | 151 | return s 152 | 153 | def grep(s, pattern): 154 | return '\n'.join(re.findall(r'^.*%s.*?$'%pattern,s,flags=re.M)) 155 | 156 | def remove_start(s, word_to_remove): 157 | return s[len(word_to_remove):] if s.startswith(word_to_remove) else "" 158 | 159 | def extract_val(out, key): 160 | val = 0 161 | if (out): 162 | key_line = grep(out, key).lstrip() 163 | if (key_line): 164 | collectd.debug('key: %s key_line: %s' % (key, key_line)) 165 | val_str = remove_start(key_line, key) 166 | collectd.debug('val_str: %s' % (val_str)) 167 | if '.' in val_str: 168 | val = long(float(val_str.replace(',', ''))) 169 | else: 170 | val = long(val_str.replace(',', '')) 171 | collectd.debug('value: %d' % (val)) 172 | else: 173 | collectd.debug('no line found with key: %s' % (key)) 174 | else: 175 | collectd.debug('nothing to process in provided output str: %s' % (out)) 176 | 177 | return val 178 | 179 | def get_physical_bytes(): 180 | bytes_written = 0 181 | bytes_read = 0 182 | 183 | if os.path.exists(cmd_fio_status): 184 | cmd = cmd_fio_status + ' ' + args_fio_status 185 | out = run_cmd(cmd) 186 | if (out): 187 | bytes_written = extract_val(out, key_bytes_written) 188 | bytes_read = extract_val(out, key_bytes_read) 189 | else: 190 | collectd.error('get_physical_bytes: failed to run cmd: %s' % (cmd)) 191 | else: 192 | collectd.warning('get_physical_bytes: %s not found' % (cmd_fio_status)) 193 | 194 | return (bytes_read, bytes_written) 195 | 196 | def get_block_erases(): 197 | b_total = 0 198 | b_min = 0 199 | b_max = 0 200 | b_avg = 0 201 | 202 | if os.path.exists(cmd_fio_get_erase_blocks): 203 | cmd = cmd_fio_get_erase_blocks + ' ' + args_fio_get_erase_blocks 204 | out = run_cmd(cmd) 205 | if (out): 206 | ebs = out.split('\n') 207 | b_total = extract_val(out, key_blocks_total) 208 | b_min = extract_val(out, key_blocks_min) 209 | b_max = extract_val(out, key_blocks_max) 210 | b_avg = extract_val(out, key_blocks_avg) 211 | else: 212 | collectd.error('get_block_erases: failed to run cmd: %s' %(cmd)) 213 | else: 214 | collectd.warning('get_block_erases: %s missing?' % (cmd_get_erase_blocks)) 215 | 216 | return (b_total, b_min, b_max, b_avg) 217 | 218 | 219 | def get_fiostats(): 220 | phy_b_r, phy_b_w = get_physical_bytes() 221 | eb_total, eb_min, eb_max, eb_avg = get_block_erases() 222 | 223 | for m in fio_white_list: 224 | fiostats_current[(m, 'ts')] = time.time() 225 | fiostats_current[('phy_bytes_written', 'val')] = phy_b_w 226 | fiostats_current[('phy_bytes_read', 'val')] = phy_b_r 227 | fiostats_current[('erased_blocks_total', 'val')] = eb_total 228 | fiostats_current[('erased_blocks_min', 'val')] = eb_min 229 | fiostats_current[('erased_blocks_max', 'val')] = eb_max 230 | fiostats_current[('erased_blocks_avg', 'val')] = eb_avg 231 | 232 | for m in fio_white_list: 233 | metric = collectd.Values() 234 | metric.host = host_name 235 | metric.plugin = 'fusionio' 236 | metric.type = 'gauge' 237 | metric.type_instance = m 238 | metric.values = [fiostats_current[(m, 'val')]] 239 | metric.dispatch() 240 | 241 | 242 | 243 | def init_stats_cache(): 244 | if os.path.exists(fio_fname): 245 | with open(fio_fname) as f: 246 | for line in f: 247 | fields = line.split() 248 | fields = [fl.strip() for fl in fields] 249 | key_name = fields[0] 250 | key_val = int(fields[2]) 251 | if any(key_name in s for s in fio_fields): 252 | stats_cache[(key_name, 'val')] = key_val 253 | stats_cache[(key_name, 'ts')] = time.time() 254 | f.close() 255 | else: 256 | collectd.info('fusionio: init_stats_cache: path: %s does not exist' 257 | % (fio_fname)) 258 | 259 | def collect_fiostats(): 260 | if os.path.exists(fio_fname): 261 | with open(fio_fname) as f: 262 | for line in f: 263 | fields = line.split() 264 | fields = [fl.strip() for fl in fields] 265 | key_name = fields[0] 266 | key_val = int(fields[2]) 267 | if any(key_name in s for s in fio_fields): 268 | metric = collectd.Values() 269 | metric.host = host_name 270 | metric.plugin = 'fusionio' 271 | metric.type = 'gauge' 272 | metric.type_instance = key_name 273 | metric.values = [key_val] 274 | stats_current[(key_name, 'val')] = key_val 275 | metric.dispatch() 276 | stats_current[(key_name, 'ts')] = time.time() 277 | f.close() 278 | else: 279 | collectd.info('fusionio: procfs path: %s does not exist' % (fio_fname)) 280 | 281 | def swap_current_cache(): 282 | for i in fio_fields: 283 | stats_cache[(i, 'val')] = stats_current[(i, 'val')] 284 | stats_cache[(i, 'ts')] = stats_current[(i, 'ts')] 285 | 286 | 287 | def configer(ObjConfiguration): 288 | collectd.info('fusionio plugin: configuring host: %s' % (host_name)) 289 | 290 | def initer(): 291 | collectd.info('fusionio plugin: host of type: %s' % (host_type)) 292 | collectd.info('fusionio initer: fields list: %s ' % (fio_fields)) 293 | init_stats_cache() 294 | collectd.info('fusionio init: stats_cache: %s ' % (stats_cache)) 295 | 296 | def reader(input_data=None): 297 | get_fiostats() 298 | collect_fiostats() 299 | #dispatch_metrics() 300 | swap_current_cache() 301 | 302 | def writer(metric, data=None): 303 | for i in metric.values: 304 | collectd.debug("%s (%s): %f" % (metric.plugin, metric.type, i)) 305 | 306 | def shutdown(): 307 | collectd.info("fusionio plugin shutting down") 308 | 309 | #== Callbacks ==# 310 | get_host_type() 311 | if ((host_type == 'search') and (os_name == 'Linux') and (is_fio_device())): 312 | collectd.register_config(configer) 313 | collectd.register_init(initer) 314 | collectd.register_read(reader) 315 | collectd.register_write(writer) 316 | collectd.register_shutdown(shutdown) 317 | else: 318 | collectd.error('fio plugin works for search hosts only; type: %s os: %s' 319 | % (host_type, os_name)) 320 | -------------------------------------------------------------------------------- /plugins/netstats.conf: -------------------------------------------------------------------------------- 1 | 2 | Globals true 3 | 4 | 5 | 6 | ModulePath "/usr/share/collectd/plugins/python" 7 | LogTraces true 8 | Interactive false 9 | Import "netstats" 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /plugins/vmstats.conf: -------------------------------------------------------------------------------- 1 | 2 | Globals true 3 | 4 | 5 | 6 | ModulePath "/usr/share/collectd/plugins/python" 7 | LogTraces true 8 | Interactive false 9 | Import "vmstats" 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /plugins/zoneinfo.conf: -------------------------------------------------------------------------------- 1 | 2 | Globals true 3 | 4 | 5 | 6 | ModulePath "/usr/share/collectd/plugins/python" 7 | LogTraces true 8 | Interactive false 9 | Import "zoneinfo" 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /plugins/zoneinfo.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | ########################################################################## 4 | # Copyright (c) 2015, Salesforce.com, Inc. 5 | # All rights reserved. 6 | # 7 | # Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # 10 | # Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer 12 | # in the documentation and/or other materials provided with the 13 | # distribution. 14 | # 15 | # Neither the name of Salesforce.com nor the names of its 16 | # contributors may be used to endorse or promote products 17 | # derived from this software without specific prior written permission. 18 | # 19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 21 | # NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23 | # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 24 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 26 | # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 28 | # IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 29 | # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 30 | # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | ########################################################################## 32 | 33 | """ 34 | **zoneinfo.py** 35 | 36 | /proc/zoneinfo breaks down virtual memory stats with respect to each 37 | NUMA node and memory zone. It supplements the measurements 38 | provided by vmstats and buddyinfo plugins. 39 | 40 | """ 41 | 42 | import collectd 43 | import platform 44 | import os 45 | import socket 46 | import time 47 | import re 48 | import sys 49 | import traceback 50 | 51 | os_name = platform.system() 52 | host_name = socket.gethostbyaddr(socket.gethostname())[0] 53 | host_types = ['app', 'db', 'ffx', 'indexer', 'search', 'other'] 54 | host_type = 'other' 55 | 56 | ZONEINFO_FNAME = '/proc/zoneinfo' 57 | 58 | METRIC_PLUGIN = 'zonefino' 59 | METRIC_TYPE = 'gauge' 60 | 61 | 62 | white_list = ['min', 63 | 'low', 64 | 'high', 65 | 'scanned', 66 | 'nr_free_pages', 67 | 'nr_dirty', 68 | 'nr_writeback', 69 | 'nr_vmscan_write', 70 | 'nr_anon_transparent_hugepages'] 71 | node_list = [] 72 | zone_list = [] 73 | 74 | stats_cache = {} 75 | stats_current = {} 76 | 77 | re_zoneinfo=re.compile(r'^\s*Node\s+(?P\d+)' 78 | r',\s+zone\s+(?P\S+)' 79 | r'(?:\n|\r\n?)' 80 | r'^\s+pages free\s+(?P\d+)' 81 | r'(?:\n|\r\n?)' 82 | r'^\s+min\s+(?P\d+)' 83 | r'(?:\n|\r\n?)' 84 | r'^\s+low\s+(?P\d+)' 85 | r'(?:\n|\r\n?)' 86 | r'^\s+high\s+(?P\d+)' 87 | r'(?:\n|\r\n?)' 88 | r'^\s+scanned\s+(?P\d+)' 89 | r'(?:\n|\r\n?)' 90 | r'(^(.+)\n)+?' 91 | r'^\s+nr_free_pages\s+(?P\d+)' 92 | r'(?:\n|\r\n?)' 93 | r'(^(.+)\n)+?' 94 | r'^\s+nr_dirty\s+(?P\d+)' 95 | r'(?:\n|\r\n?)' 96 | r'^\s+nr_writeback\s+(?P\d+)' 97 | r'(?:\n|\r\n?)' 98 | r'(^(.+)\n)+?' 99 | r'^\s+nr_vmscan_write\s+(?P\d+)' 100 | r'(?:\n|\r\n?)' 101 | r'(^(.+)\n)+?' 102 | r'^\s+nr_anon_transparent_hugepages\s+(?P\d+)' 103 | , re.MULTILINE) 104 | 105 | def get_host_type(): 106 | for i in host_types: 107 | if i in host_name: 108 | host_type = i 109 | 110 | def init_stats_cache(): 111 | try: 112 | if os.path.exists(ZONEINFO_FNAME): 113 | with open(ZONEINFO_FNAME) as f: 114 | match = re.finditer(re_zoneinfo, f.read()) 115 | if not match: 116 | collectd.error('zoneinfo: init: pattern not found') 117 | return 118 | for m in match: 119 | if 'node' in m.groupdict(): 120 | node = m.group('node') 121 | else: 122 | collectd.error('node not found in zoneinfo') 123 | return 124 | if 'zone' in m.groupdict(): 125 | zone = m.group('zone') 126 | else: 127 | collectd.error('zone not found in zoneinfo') 128 | return 129 | if node not in node_list: 130 | node_list.append(node) 131 | if zone not in zone_list: 132 | zone_list.append(zone) 133 | 134 | zone_pages = [] 135 | for i in white_list: 136 | if i in m.groupdict(): 137 | zone_pages.append(m.group(i)) 138 | else: 139 | collectd.error(i + ' not found in zoneinfo') 140 | return 141 | 142 | stats_cache[(node, zone, 'val')] = zone_pages 143 | stats_cache[(node, zone, 'ts')] = time.time() 144 | 145 | f.close() 146 | collectd.info('node_list: %s' % (node_list)) 147 | collectd.info('zone_list: %s' % (zone_list)) 148 | collectd.info('white_list: %s' % (white_list)) 149 | else: 150 | collectd.error('zoneinfo: init: procfs path: %s does not exist' 151 | % (ZONEINFO_FNAME)) 152 | except Exception as e: 153 | exc_type, exc_value, exc_traceback = sys.exc_info() 154 | collectd.error('Exception during zoneinfo init: %s\n%s' % 155 | (str(e), traceback.format_tb(exc_traceback))) 156 | 157 | def collect_zoneinfo(): 158 | try: 159 | if os.path.exists(ZONEINFO_FNAME): 160 | with open(ZONEINFO_FNAME) as f: 161 | match = re.finditer(re_zoneinfo, f.read()) 162 | if not match: 163 | collectd.error('zoneinfo: collect: pattern not found') 164 | return 165 | for m in match: 166 | zone_pages = [] 167 | if 'node' in m.groupdict(): 168 | node = m.group('node') 169 | else: 170 | collectd.error('node not found in zoneinfo') 171 | return 172 | if 'zone' in m.groupdict(): 173 | zone = m.group('zone') 174 | else: 175 | collectd.error('zone not found in zoneinfo') 176 | return 177 | for i in white_list: 178 | if i in m.groupdict(): 179 | zone_pages.append(m.group(i)) 180 | else: 181 | collectd.error(i + ' not found in zoneinfo') 182 | return 183 | stats_current[(node, zone, 'val')] = zone_pages 184 | stats_current[(node, zone, 'ts')] = time.time() 185 | metric = collectd.Values() 186 | metric.host = host_name 187 | metric.plugin = METRIC_PLUGIN 188 | metric.plugin_instance = node 189 | metric.type = METRIC_TYPE 190 | for k in range(0, len(white_list)): 191 | metric.type_instance = 'zone_' + zone + '_' 192 | metric.type_instance += white_list[k] 193 | metric.values = [zone_pages[k]] 194 | metric.dispatch() 195 | 196 | f.close() 197 | else: 198 | collectd.error('zoneinfo: collect: procfs path: %s does not exist' 199 | % (ZONEINFO_FNAME)) 200 | except Exception as e: 201 | exc_type, exc_value, exc_traceback = sys.exc_info() 202 | collectd.error('Exception during zoneinfo collection: %s\n%s' % 203 | (str(e), traceback.format_tb(exc_traceback))) 204 | 205 | def swap_current_cache(): 206 | stats_cache = stats_current.copy() 207 | 208 | def configer(ObjConfiguration): 209 | collectd.info('zoneinfo plugin: configuring host: %s' % (host_name)) 210 | 211 | def initer(): 212 | get_host_type() 213 | collectd.info('zoneinfo plugin: host of type: %s' % (host_type)) 214 | collectd.info('zoneinfo initer: white list: %s ' % (white_list)) 215 | init_stats_cache() 216 | collectd.info('zoneinfo init: stats_cache: %s' % (stats_cache)) 217 | 218 | def reader(input_data=None): 219 | collect_zoneinfo() 220 | swap_current_cache() 221 | 222 | def writer(metric, data=None): 223 | for i in metric.values: 224 | collectd.debug("%s (%s): %f" % (metric.plugin, metric.type, i)) 225 | 226 | def shutdown(): 227 | collectd.info("zoneinfo plugin shutting down") 228 | 229 | #== Callbacks ==# 230 | if (os_name == 'Linux'): 231 | collectd.register_config(configer) 232 | collectd.register_init(initer) 233 | collectd.register_read(reader) 234 | collectd.register_write(writer) 235 | collectd.register_shutdown(shutdown) 236 | else: 237 | collectd.warning('zoneinfo plugin currently works for Linux only') 238 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from __future__ import with_statement 4 | 5 | import os 6 | 7 | from setuptools import setup 8 | 9 | setup_kwargs = dict(zip_safe=0) 10 | 11 | data_files = [ 12 | ('/usr/share/collectd/plugins/python', ['plugins/diskstats.py', 13 | 'plugins/vmstats.py', 14 | 'plugins/buddyinfo.py', 15 | 'plugins/zoneinfo.py', 16 | 'plugins/netstats.py', 17 | 'plugins/fusionio.py']), 18 | ('/etc/collectd.d', ['plugins/diskstats.conf', 19 | 'plugins/vmstats.conf', 20 | 'plugins/buddyinfo.conf', 21 | 'plugins/zoneinfo.conf', 22 | 'plugins/netstats.conf', 23 | 'plugins/fusionio.conf']), 24 | ] 25 | 26 | setup( 27 | name='collectd-linuxtelemetry', 28 | version='0.3.1', 29 | url='https://git.soma.salesforce.com/SolrTelemetry/telemetry', 30 | author='Abdul Waheed', 31 | author_email='awaheed@salesforce.com', 32 | license='BSD 3-Clause', 33 | description='collectd plugins to monitor Linux system metrics', 34 | long_description='Collects Linux system metrics for cloud infrastructure monitoring, tuning, capacity planning, and analytics', 35 | packages=[], 36 | package_dir={'': 'plugins'}, 37 | data_files=data_files, 38 | **setup_kwargs 39 | ) 40 | -------------------------------------------------------------------------------- /tests/buddyinfo_utest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | ########################################################################## 4 | # Copyright (c) 2015, Salesforce.com, Inc. 5 | # All rights reserved. 6 | # 7 | # Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # 10 | # Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer 12 | # in the documentation and/or other materials provided with the 13 | # distribution. 14 | # 15 | # Neither the name of Salesforce.com nor the names of its 16 | # contributors may be used to endorse or promote products 17 | # derived from this software without specific prior written permission. 18 | # 19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 21 | # NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23 | # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 24 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 26 | # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 28 | # IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 29 | # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 30 | # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | ########################################################################## 32 | 33 | ############################################################ 34 | # Unit test for buddyinfo plugin 35 | ############################################################ 36 | 37 | import os 38 | import sys 39 | import unittest 40 | 41 | from mock import Mock, patch 42 | 43 | import collectd 44 | sys.path.append(os.path.join(os.path.dirname(__file__), "../plugins")) 45 | import buddyinfo 46 | 47 | PROCFS_BUDDYINFO = os.path.abspath(os.path.join(os.path.dirname(__file__), 48 | 'mocks/proc_buddyinfo')) 49 | 50 | # Expected values for verifications 51 | WHITE_LIST = ['free_pages_4K', 'free_pages_8K', 'free_pages_16K', 'free_pages_32K', 'free_pages_64K', 'free_pages_128K', 'free_pages_256K', 'free_pages_512K', 'free_pages_1024K', 'free_pages_2048K', 'free_pages_4096K'] 52 | 53 | 54 | class TestBuddyinfo(unittest.TestCase): 55 | def setUp(self): 56 | buddyinfo.BUDDYINFO_FNAME = PROCFS_BUDDYINFO 57 | 58 | def test_1_buddyinfo_get_host_type(self): 59 | buddyinfo.get_host_type() 60 | self.assertTrue(buddyinfo.host_type is 'other', 'unknown host type') 61 | 62 | def test_2_buddyinfo_white_list(self): 63 | buddyinfo.init_stats_cache() 64 | 65 | self.assertTrue(len(buddyinfo.white_list) > 0, 'at least one metric') 66 | self.assertEqual(buddyinfo.white_list, WHITE_LIST, 67 | 'white lists parsing error') 68 | 69 | @patch('collectd.Values') 70 | def test_3_buddyinfo_collection(self, collectdValues): 71 | collectdValues.vals = Mock() 72 | buddyinfo.collect_buddyinfo() 73 | 74 | collectdValues.assert_called_once() 75 | self.assertTrue(len(buddyinfo.stats_cache) > 0, 'at least one udp counter') 76 | 77 | if __name__ == '__main__': 78 | suite = unittest.TestLoader().loadTestsFromTestCase(TestBuddyinfo) 79 | unittest.TextTestRunner(verbosity=2).run(suite) 80 | -------------------------------------------------------------------------------- /tests/collectd.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | ########################################################################## 4 | # Copyright (c) 2015, Salesforce.com, Inc. 5 | # All rights reserved. 6 | # 7 | # Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # 10 | # Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer 12 | # in the documentation and/or other materials provided with the 13 | # distribution. 14 | # 15 | # Neither the name of Salesforce.com nor the names of its 16 | # contributors may be used to endorse or promote products 17 | # derived from this software without specific prior written permission. 18 | # 19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 21 | # NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23 | # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 24 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 26 | # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 28 | # IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 29 | # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 30 | # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | ########################################################################## 32 | 33 | ############################################################ 34 | # Mockup for collectd for testing plugins as well as for 35 | # generating docs 36 | ############################################################ 37 | 38 | import socket 39 | 40 | class Values: 41 | def __init__(self): 42 | self.host = socket.gethostbyaddr(socket.gethostname())[0] 43 | self.plugin = 'test-plugin' 44 | self.type = 'test-type' 45 | self.type_instance = 'test-type-instance' 46 | self.values = [] 47 | 48 | def dispatch(self): 49 | print('dispatch: type_instance: %s value: %s' % (self.type_instance, self.values)) 50 | 51 | def info(params): 52 | print('INFO: ' + params) 53 | 54 | def warn(params): 55 | print('WARN: ' + params) 56 | 57 | def error(params): 58 | print('ERROR: ' + params) 59 | 60 | def debug(params): 61 | print('DEBUG: ' + params) 62 | 63 | def register_config(params): 64 | pass 65 | 66 | def register_init(params): 67 | pass 68 | 69 | def register_read(params): 70 | pass 71 | 72 | def register_write(params): 73 | pass 74 | 75 | def register_shutdown(params): 76 | pass 77 | -------------------------------------------------------------------------------- /tests/diskstats_ftest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | ########################################################################## 4 | # Copyright (c) 2015, Salesforce.com, Inc. 5 | # All rights reserved. 6 | # 7 | # Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # 10 | # Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer 12 | # in the documentation and/or other materials provided with the 13 | # distribution. 14 | # 15 | # Neither the name of Salesforce.com nor the names of its 16 | # contributors may be used to endorse or promote products 17 | # derived from this software without specific prior written permission. 18 | # 19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 21 | # NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23 | # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 24 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 26 | # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 28 | # IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 29 | # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 30 | # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | ########################################################################## 32 | 33 | """ 34 | Function test for diskstats plugin regex, parser, and 'iostat 10 1' 35 | emulation with dev metrics over 10 seconds interval. Verify results on 36 | a Linux host using iostat or atop. 37 | """ 38 | import sys 39 | import os 40 | import time 41 | import logging 42 | 43 | import collectd 44 | sys.path.append(os.path.join(os.path.dirname(__file__), "../plugins")) 45 | import diskstats 46 | 47 | 48 | def print_header(): 49 | str = 'Device: tps B_read/s B_wrtn/s' 50 | print(str) 51 | 52 | def dev_pretty_prints(dev, vals): 53 | st = dev 54 | for i in range(len(vals)): 55 | st += ' %20.2f' % vals[i] 56 | print('%s' % (st)) 57 | 58 | def main(): 59 | if (diskstats.OS_NAME != 'Linux'): 60 | print('diskstats plugin currently works for Linux only') 61 | print('os_name: %s' % (diskstats.os_name)) 62 | print('Finished') 63 | return 64 | 65 | logging.basicConfig(level=logging.INFO) 66 | diskstats.get_dev_list() 67 | diskstats.dev_stats_cache = diskstats.collect_diskstats() 68 | logging.info('netstats_ftest: dev_list: %s' % (diskstats.dev_list)) 69 | logging.debug('netstats_ftest: dev_stats_cache: %s' 70 | % (diskstats.dev_stats_cache)) 71 | print('netstats_ftest: ... sleeping for 10 sec...') 72 | time.sleep(10) 73 | diskstats.dev_stats_current = diskstats.collect_diskstats() 74 | logging.debug('netstats_ftest: dev_stats_cur: %s' 75 | % (diskstats.dev_stats_current)) 76 | metric_names = ['iops_rw', 'bytes_ps_read', 'bytes_ps_write'] 77 | 78 | print_header() 79 | metric_key_vals = {} 80 | metric_vals = [] 81 | for i in diskstats.dev_list: 82 | metric_key_vals = diskstats.calc_metrics(i) 83 | logging.debug('metric_key_vals: %s' % (metric_key_vals)) 84 | metric_vals = [metric_key_vals[k] for k in metric_names] 85 | dev_pretty_prints(i, metric_vals) 86 | logging.debug('metric_vals: %s' % (metric_vals)) 87 | 88 | if __name__ == "__main__": 89 | main() 90 | -------------------------------------------------------------------------------- /tests/diskstats_utest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | ########################################################################## 4 | # Copyright (c) 2015, Salesforce.com, Inc. 5 | # All rights reserved. 6 | # 7 | # Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # 10 | # Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer 12 | # in the documentation and/or other materials provided with the 13 | # distribution. 14 | # 15 | # Neither the name of Salesforce.com nor the names of its 16 | # contributors may be used to endorse or promote products 17 | # derived from this software without specific prior written permission. 18 | # 19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 21 | # NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23 | # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 24 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 26 | # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 28 | # IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 29 | # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 30 | # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | ########################################################################## 32 | 33 | ############################################################ 34 | # Unit test for diskstatss plugin 35 | ############################################################ 36 | 37 | import os 38 | import sys 39 | import unittest 40 | 41 | from mock import Mock, patch 42 | 43 | import collectd 44 | sys.path.append(os.path.join(os.path.dirname(__file__), "../plugins")) 45 | import diskstats 46 | 47 | # SKU1: 6 disks in sw raid10 config + fioa 48 | PROCFS_DISKSTAT = os.path.abspath(os.path.join(os.path.dirname(__file__), 49 | 'mocks/proc_diskstats')) 50 | # SKU2: 4 disks in hw raid10 config + ssd 51 | PROCFS_DISKSTAT_2 = os.path.abspath(os.path.join(os.path.dirname(__file__), 52 | 'mocks/proc_diskstats_2')) 53 | 54 | # Expected values for verifications 55 | DEV_LIST = ['sdb', 'sde', 'sdd', 'sdf', 'sdc', 'sda', 'fioa'] 56 | DEV_LIST_2 = ['ram0', 'ram1', 'ram2', 'ram3', 'ram4', 'ram5', 'ram6', 'ram7', 'ram8', 'ram9', 'ram10', 'ram11', 'ram12', 'ram13', 'ram14', 'ram15', 'loop0', 'loop1', 'loop2', 'loop3', 'loop4', 'loop5', 'loop6', 'loop7', 'sdb', 'sda', 'sda1', 'sda2', 'sda3', 'sda4', 'sr0'] 57 | 58 | class TestDiskstats(unittest.TestCase): 59 | def setUp(self): 60 | diskstats.DISKSTATS_FNAME = PROCFS_DISKSTAT 61 | diskstats.device_filter_regexes=['^sd[a-z]+$','^fioa$'] 62 | 63 | def test_1_diskstats_get_dev_list_sku1(self): 64 | diskstats.get_dev_list() 65 | 66 | try: 67 | self.assertTrue(len(diskstats.dev_list) > 0, 'at least one metric') 68 | self.assertEqual(diskstats.dev_list, DEV_LIST, 'device lists parsing error') 69 | except: 70 | print('dev_list: %s' % (diskstats.dev_list)) 71 | print('expected DEV_LIST: %s' % (DEV_LIST)) 72 | print('Exception: %s' % (sys.exc_info()[0])) 73 | raise 74 | 75 | def test_1_diskstats_get_dev_list_sku2(self): 76 | diskstats.dev_list = [] 77 | diskstats.DISKSTATS_FNAME = PROCFS_DISKSTAT_2 78 | diskstats.device_filter_regexes = [''] 79 | diskstats.get_dev_list() 80 | 81 | self.assertTrue(len(diskstats.dev_list) > 0, 'at least one metric') 82 | self.assertEqual(diskstats.dev_list, DEV_LIST_2, 83 | 'device lists parsing error') 84 | try: 85 | self.assertTrue(len(diskstats.dev_list) > 0, 'at least one metric') 86 | self.assertEqual(diskstats.dev_list, DEV_LIST_2, 'device lists parsing error') 87 | except: 88 | print('dev_list: %s' % (diskstats.dev_list)) 89 | print('expected DEV_LIST: %s' % (DEV_LIST_2)) 90 | print('Exception: %s' % (sys.exc_info()[0])) 91 | raise 92 | 93 | # restore the default SKU 94 | diskstats.DISKSTATS_FNAME = PROCFS_DISKSTAT 95 | 96 | def test_2_diskstats_collection(self): 97 | diskstats.dev_list = [] 98 | diskstats.DISKSTATS_FNAME = PROCFS_DISKSTAT 99 | diskstats.get_dev_list() 100 | stats_names = diskstats.diskstat_fields[3:14] 101 | dev_stats_current = diskstats.collect_diskstats() 102 | 103 | field_names = [dev_stats_current[(diskstats.dev_list[0], k)] for k in 104 | stats_names] 105 | num_dev = len(diskstats.dev_list) 106 | num_fields = len(field_names) 107 | num_expected_fields = (num_fields + 1) * num_dev; 108 | self.assertTrue(len(dev_stats_current) > 0, 109 | 'at least one metric') 110 | try: 111 | self.assertEqual(len(dev_stats_current), num_expected_fields, 112 | 'unexpected diskstat fields and vals') 113 | except: 114 | print('dev_stats_current: %s' % (dev_stats_current)) 115 | print('field_names: %s' % (field_names)) 116 | print('dev_stats_current len: %d' % (len(dev_stats_current))) 117 | print('Exception: %s' % (sys.exc_info()[0])) 118 | raise 119 | 120 | def test_3_diskstats_metrics_calc(self): 121 | diskstats.dev_stats_cache = diskstats.collect_diskstats() 122 | diskstats.dev_stats_current = diskstats.collect_diskstats() 123 | metrics_key_vals = diskstats.calc_metrics(diskstats.dev_list[0]) 124 | dev_metrics_vals = metrics_key_vals.values() 125 | 126 | num_metrics_keys = len(diskstats.diskstat_metrics) 127 | num_metrics_vals = len(dev_metrics_vals) 128 | 129 | try: 130 | self.assertEqual(num_metrics_keys, num_metrics_vals, 131 | 'number of metric names not equals to vals') 132 | self.assertEqual(metrics_key_vals['util_pct'], 0.0, 'wrong util_pct') 133 | self.assertEqual(metrics_key_vals['bytes_per_write'], None, 134 | 'wrong bytes_per_write value') 135 | except: 136 | print('del_t: %f' % (diskstats.calc_del_t(diskstats.dev_list[0]))) 137 | print('metris_key_vals: %s' % (metrics_key_vals)) 138 | print('Exception: %s' % (sys.exc_info()[0])) 139 | raise 140 | 141 | def test_4_diskstats_swap_cache(self): 142 | st_names = diskstats.diskstat_fields[3:14] 143 | diskstats.dev_stats_cache = diskstats.collect_diskstats() 144 | diskstats.dev_stats_current = diskstats.collect_diskstats() 145 | diskstats.swap_current_cache() 146 | diskstats.dev_stats_current = diskstats.collect_diskstats() 147 | 148 | for i in diskstats.dev_list: 149 | self.assertNotEqual(diskstats.dev_stats_cache[(i, 'ts')], 150 | diskstats.dev_stats_current[(i, 'ts')], 151 | 'prev and curr timestamps should differ') 152 | self.assertEqual([diskstats.dev_stats_cache[(i,k)] for k in st_names], 153 | [diskstats.dev_stats_current[(i,k)] for k in st_names], 154 | 'prev and curr dev stats should be same') 155 | 156 | if __name__ == '__main__': 157 | suite = unittest.TestLoader().loadTestsFromTestCase(TestDiskstats) 158 | unittest.TextTestRunner(verbosity=2).run(suite) 159 | -------------------------------------------------------------------------------- /tests/netstats_ftest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | ########################################################################## 4 | # Copyright (c) 2015, Salesforce.com, Inc. 5 | # All rights reserved. 6 | # 7 | # Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # 10 | # Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer 12 | # in the documentation and/or other materials provided with the 13 | # distribution. 14 | # 15 | # Neither the name of Salesforce.com nor the names of its 16 | # contributors may be used to endorse or promote products 17 | # derived from this software without specific prior written permission. 18 | # 19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 21 | # NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23 | # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 24 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 26 | # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 28 | # IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 29 | # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 30 | # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | ########################################################################## 32 | 33 | """ 34 | Test for netstat plugin regex, parser, and 'netstat -s' 35 | emulation with interpretation of snmp linux MIB 36 | definitions. 37 | """ 38 | 39 | import sys 40 | import os 41 | 42 | import collectd 43 | sys.path.append(os.path.join(os.path.dirname(__file__), "../plugins")) 44 | import netstats 45 | 46 | stats_cache = {} 47 | 48 | ip_metrics = [ 49 | ['InReceives', 'total packets received'], 50 | ['InHdrErrors','with invalid addresses'], 51 | ['ForwDatagrams','forwarded'], 52 | ['InDiscards','incoming packets discarded'], 53 | ['InDelivers','incoming packets delivered'], 54 | ['OutRequests','requests sent out'], 55 | ['OutNoRoutes','fragments dropped_after timeout'], 56 | ['ReasmReqds','reassemblies required'], 57 | ['ReasmOKs','packets reassembled ok'], 58 | ['ReasmFails', 'packet reassembles failed'] 59 | ] 60 | 61 | icmp_metrics = [ 62 | ['InMsgs', 'ICMP messages received'], 63 | ['InErrors', 'input ICMP message failed'], 64 | ['InDestUnreachs', 'destination unreachable'], 65 | ['InTimeExcds', 'timeout in transit'], 66 | ['InParmProbs', 'wrong parameters'], 67 | ['InSrcQuenchs', 'source quenches'], 68 | ['InRedirects', 'redirects'], 69 | ['InEchos', 'echo requests'], 70 | ['InEchoReps', 'echo replies'], 71 | ['InTimestamps', 'timestamp request'], 72 | ['InTimestampReps', 'timestamp reply'], 73 | ['InAddrMasks', 'address mask request'], 74 | ['InAddrMaskReps', 'address mask replies'], 75 | ['OutMsgs', 'ICMP messages sent'], 76 | ['OutErrors', 'ICMP messages failed'], 77 | ['OutDestUnreachs', 'destination unreachable'], 78 | ['OutTimeExcds', 'time exceeded'], 79 | ['OutParmProbs', 'wrong parameters'], 80 | ['OutSrcQuenchs', 'source quench'], 81 | ['OutRedirects', 'redirect'], 82 | ['OutEchos', 'echo request'], 83 | ['OutEchoReps', 'echo replies'], 84 | ['OutTimestamps', 'timestamp requests'], 85 | ['OutTimestampReps', 'timestamp replies'], 86 | ['OutAddrMasks', 'address mask requests'], 87 | ['OutAddrMaskReps', 'address mask replies'] 88 | ] 89 | 90 | tcp_metrics = [ 91 | ['RtoAlgorithm', 'RTO algorithm'], 92 | ['RtoMin', 'RTO min'], 93 | ['RtoMax', 'RTO max'], 94 | ['MaxConn', 'Max connections'], 95 | ['ActiveOpens', 'active connections openings'], 96 | ['PassiveOpens', 'passive connection openings'], 97 | ['AttemptFails', 'failed connection attempts'], 98 | ['EstabResets', 'connection resets received'], 99 | ['CurrEstab', 'connections established'], 100 | ['InSegs', 'segments received'], 101 | ['OutSegs', 'segments send out'], 102 | ['RetransSegs', 'segments retransmited'], 103 | ['InErrs', 'bad segments received'], 104 | ['OutRsts', 'resets sent'] 105 | ] 106 | udp_metrics = [ 107 | ['InDatagrams', 'packets received'], 108 | ['NoPorts', 'packets to unknown port received'], 109 | ['InErrors', 'packet receive errors'], 110 | ['OutDatagrams', 'packets sent'], 111 | ['RcvbufErrors', 'receive buffer errors'], 112 | ['SndbufErrors', 'send buffer errors'] 113 | ] 114 | tcpext_metrics = [ 115 | ['SyncookiesSent', 'SYN cookies sent'], 116 | ['SyncookiesRecv', 'SYN cookies received'], 117 | ['SyncookiesFailed', 'invalid SYN cookies received'], 118 | ['EmbryonicRsts', 'resets received for embryonic SYN_RECV sockets'], 119 | ['PruneCalled', 'pkts pruned from recv queue because of soc buf overrun'], 120 | ['RcvPruned', ' pkts pruned from receive queue'], 121 | ['OfoPruned', 'pkts dropped from o-o-order queue b/c of sock buf overrun'], 122 | ['OutOfWindowIcmps', 'ICMP pkts dropped because they were out-of-window'], 123 | ['LockDroppedIcmps', 'ICMP packets dropped because socket was locked'], 124 | ['TW', 'TCP sockets finished time wait in fast timer'], 125 | ['TWRecycled', 'time wait sockets recycled by time stamp'], 126 | ['TWKilled', 'TCP sockets finished time wait in slow timer'], 127 | ['PAWSPassive', 'passive connections rejected because of time stamp'], 128 | ['PAWSActive', 'active connections rejected because of time stamp'], 129 | ['PAWSEstab', 'pkts rejects in estab connections because of timestamp'], 130 | ['DelayedACKs', 'delayed acks sent'], 131 | ['DelayedACKLocked', 'delayed acks further delayed b/c of locked socket'], 132 | ['DelayedACKLost', 'times quick ack mode was activated'], 133 | ['ListenOverflows', 'times the listen queue of a socket overflowed'], 134 | ['ListenDrops', 'SYNs to LISTEN sockets ignored'], 135 | ['TCPPrequeued', 'packets directly queued to recvmsg prequeue'], 136 | ['TCPDirectCopyFromBacklog', 'packets directly received from backlog'], 137 | ['TCPDirectCopyFromPrequeue', 'packets directly received from prequeue'], 138 | ['TCPPrequeueDropped', 'packets dropped from prequeue'], 139 | ['TCPHPHits', 'packets header predicted'], 140 | ['TCPHPHitsToUser', 'packets header predicted and directly queued to user'], 141 | ['TCPPureAcks', 'acknowledgments not containing data received'], 142 | ['TCPHPAcks', 'predicted acknowledgments in TCP fast path'], 143 | ['TCPLossFailures', 'TCP data loss events'], 144 | ['TCPTimeouts', 'TCP timeout events'], 145 | ['TCPDSACKOldSent', 'DSACKs sent for old packets'], 146 | ['TCPAbortOnData', 'connections reset due to unexpected data'], 147 | ['TCPAbortOnClose', 'connections reset due to early user close'], 148 | ['TCPAbortOnTimeout', 'connections aborted due to timeout'] 149 | ] 150 | 151 | ipext_metrics = [ 152 | ['InMcastPkts', 'multicast packets received'], 153 | ['OutMcastPkts', 'multicast packets sent'], 154 | ['InBcastPkts', 'broadcast packets received'], 155 | ['InOctets', 'octets received'], 156 | ['OutOctets', 'octets sent'], 157 | ['InMcastOctets', 'multicast octets received'], 158 | ['OutMcastOctets', 'multicast octets sent'], 159 | ['InBcastOctets', 'broadcast octets received'] 160 | ] 161 | 162 | def collect_labels_and_stats(proto, labels, vals): 163 | global stats_cache 164 | print('\nAll counters for %s:' % (proto)) 165 | for i in range(0, len(labels)): 166 | stats_cache[(proto, labels[i])] = vals[i] 167 | print('%s : %s' % (labels[i], vals[i])) 168 | 169 | def protocol_pretty_prints(proto, metrics, stats): 170 | print('\n%s: ' % (proto)) 171 | for i in range(0, len(metrics)): 172 | val = 'unknown' 173 | label = metrics[i][0] 174 | key = (proto, label) 175 | if key in stats: 176 | val = stats[key] 177 | if label in netstats.white_list: 178 | print('%20s : %50s : %10s' 179 | % (metrics[i][0], 180 | metrics[i][1], 181 | val)) 182 | 183 | def netstats_sum_stats(): 184 | collect_labels_and_stats("ip", netstats.ip_list, netstats.ip_vals) 185 | collect_labels_and_stats("icmp", netstats.icmp_list, netstats.icmp_vals) 186 | collect_labels_and_stats("icmpmsg", netstats.icmpmsg_list, 187 | netstats.icmpmsg_vals) 188 | collect_labels_and_stats("tcp", netstats.tcp_list, netstats.tcp_vals) 189 | collect_labels_and_stats("udp", netstats.udp_list, netstats.udp_vals) 190 | collect_labels_and_stats("udplite", netstats.udplite_list, 191 | netstats.udplite_vals) 192 | collect_labels_and_stats("tcpext", netstats.tcpext_list, 193 | netstats.tcpext_vals) 194 | collect_labels_and_stats("ipext", netstats.ipext_list, netstats.ipext_vals) 195 | 196 | print('\n\nSummary statistics similar to \'netstat -s\'') 197 | protocol_pretty_prints('ip', ip_metrics, stats_cache) 198 | protocol_pretty_prints('icmp', icmp_metrics, stats_cache) 199 | protocol_pretty_prints('tcp', tcp_metrics, stats_cache) 200 | protocol_pretty_prints('udp', udp_metrics, stats_cache) 201 | protocol_pretty_prints('tcpext', tcpext_metrics, stats_cache) 202 | protocol_pretty_prints('ipext', ipext_metrics, stats_cache) 203 | 204 | def main(): 205 | if (netstats.os_name != 'Linux'): 206 | print('netstat plugin currently works for Linux only') 207 | print('os_name: %s' % (netstats.os_name)) 208 | print('Finished') 209 | return 210 | 211 | netstats.initer() 212 | netstats.collect_netstats() 213 | netstats_sum_stats() 214 | 215 | if __name__ == "__main__": 216 | main() 217 | -------------------------------------------------------------------------------- /tests/netstats_utest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | ########################################################################## 4 | # Copyright (c) 2015, Salesforce.com, Inc. 5 | # All rights reserved. 6 | # 7 | # Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # 10 | # Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer 12 | # in the documentation and/or other materials provided with the 13 | # distribution. 14 | # 15 | # Neither the name of Salesforce.com nor the names of its 16 | # contributors may be used to endorse or promote products 17 | # derived from this software without specific prior written permission. 18 | # 19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 21 | # NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23 | # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 24 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 26 | # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 28 | # IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 29 | # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 30 | # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | ########################################################################## 32 | 33 | ############################################################ 34 | # Unit test for buddyinfo plugin 35 | ############################################################ 36 | 37 | import os 38 | import sys 39 | import unittest 40 | 41 | import collectd 42 | sys.path.append(os.path.join(os.path.dirname(__file__), "../plugins")) 43 | import netstats 44 | 45 | PROCFS_SNMP = os.path.abspath(os.path.join(os.path.dirname(__file__), 46 | 'mocks/proc_net_snmp')) 47 | PROCFS_NETSTAT = os.path.abspath(os.path.join(os.path.dirname(__file__), 48 | 'mocks/proc_net_netstat')) 49 | 50 | # Expected values for verifications 51 | WHITE_LIST = ['InReceives', 'InHdrErrors', 'ForwDatagrams', 'InDiscards', 'InDelivers', 'OutRequests', 'OutNoRoutes', 'ReasmReqds', 'ReasmOKs', 'ReasmFails', 'InMsgs', 'InErrors', 'InDestUnreachs', 'InEchos', 'InTimestamps', 'InAddrMasks', 'OutMsgs', 'OutDestUnreachs', 'OutEchoReps', 'OutTimestampReps', 'ActiveOpens', 'PassiveOpens', 'AttemptFails', 'EstabResets', 'CurrEstab', 'InSegs', 'OutSegs', 'RetransSegs', 'InErrs', 'OutRsts', 'InDatagrams', 'NoPorts', 'InErrors', 'OutDatagrams', 'RcvbufErrors', 'SndbufErrors', 'SyncookiesFailed', 'EmbryonicRsts', 'TW', 'DelayedACKs', 'DelayedACKLocked', 'DelayedACKLost', 'TCPPrequeued', 'TCPHPHits', 'TCPPureAcks', 'TCPHPAcks', 'TCPLossFailures', 'TCPTimeouts', 'TCPDSACKOldSent', 'TCPAbortOnData', 'TCPAbortOnClose', 'TCPAbortOnTimeout', 'InMcastPkts', 'OutMcastPkts', 'InBcastPkts', 'InOctets', 'OutOctets', 'InMcastOctets', 'OutMcastOctets', 'InBcastOctets'] 52 | 53 | IP_VALS = ['2', '64', '193667093', '0', '622', '0', '0', '0', '178978597', '8430305', '0', '0', '15', '6026610', '3013266', '15', '0', '0', '0'] 54 | 55 | class TestNetstats(unittest.TestCase): 56 | def setUp(self): 57 | netstats.SNMP_FNAME = PROCFS_SNMP 58 | netstats.NETSTAT_FNAME = PROCFS_NETSTAT 59 | 60 | def test_1_netstats_get_host_type(self): 61 | netstats.get_host_type() 62 | self.assertTrue(netstats.host_type is 'other', 'unknown host type') 63 | 64 | def test_2_netstats_white_list(self): 65 | netstats.init_snmp_counters_list() 66 | netstats.init_netstat_counters_list() 67 | self.assertTrue(len(netstats.ip_list) > 0, 'at least one ip counter') 68 | self.assertTrue(len(netstats.icmp_list) > 0, 'at least one icmp counter') 69 | self.assertTrue(len(netstats.tcp_list) > 0, 'at least one tcp counter') 70 | self.assertTrue(len(netstats.udp_list) > 0, 'at least one udp counter') 71 | self.assertTrue(len(netstats.tcpext_list) > 0, 72 | 'at least one tcpext counter') 73 | self.assertTrue(len(netstats.ipext_list) > 0, 74 | 'at least one ipext counter') 75 | self.assertEqual(netstats.white_list, WHITE_LIST, 76 | 'white lists parsing error') 77 | 78 | def test_3_netstats_collection(self): 79 | netstats.collect_netstats() 80 | self.assertTrue(len(netstats.ip_vals) > 0, 'at least one ip counter') 81 | self.assertTrue(len(netstats.icmp_vals) > 0, 'at least one icmp counter') 82 | self.assertTrue(len(netstats.tcp_vals) > 0, 'at least one tcp counter') 83 | self.assertTrue(len(netstats.udp_vals) > 0, 'at least one udp counter') 84 | self.assertTrue(len(netstats.tcpext_vals) > 0, 85 | 'at least one tcpext counter') 86 | self.assertTrue(len(netstats.ipext_vals) > 0, 87 | 'at least one ipext counter') 88 | self.assertEqual(netstats.ip_vals, IP_VALS, 'ip counts mis-match') 89 | 90 | if __name__ == '__main__': 91 | suite = unittest.TestLoader().loadTestsFromTestCase(TestNetstats) 92 | unittest.TextTestRunner(verbosity=2).run(suite) 93 | -------------------------------------------------------------------------------- /tests/vmstats_ftest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | ########################################################################## 4 | # Copyright (c) 2019, Salesforce.com, Inc. 5 | # All rights reserved. 6 | # 7 | # Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # 10 | # Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer 12 | # in the documentation and/or other materials provided with the 13 | # distribution. 14 | # 15 | # Neither the name of Salesforce.com nor the names of its 16 | # contributors may be used to endorse or promote products 17 | # derived from this software without specific prior written permission. 18 | # 19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 21 | # NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23 | # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 24 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 26 | # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 28 | # IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 29 | # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 30 | # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | ########################################################################## 32 | 33 | ############################################################ 34 | # Ftest for vmstat plugin with some ideas to extend it for 35 | # 3.x kernel, which has slightly different pgsteal_* fields. 36 | ############################################################ 37 | 38 | import platform 39 | import sys 40 | import os 41 | import socket 42 | import time 43 | import re 44 | 45 | sys.path.append(os.path.join(os.path.dirname(__file__), "../src")) 46 | from sfdc.collectd import vmstats 47 | import collectd 48 | 49 | def main(): 50 | os_name = platform.system() 51 | if (os_name == 'Linux'): 52 | vmstats.initer() 53 | vmstats.reader() 54 | print('read once') 55 | time.sleep(10) 56 | vmstats.reader() 57 | print('read twice') 58 | else: 59 | print('vmstats plugin currently works for Linux only') 60 | print('Finished') 61 | 62 | if __name__ == "__main__": 63 | main() 64 | -------------------------------------------------------------------------------- /tests/vmstats_utest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | ########################################################################## 4 | # Copyright (c) 2015, Salesforce.com, Inc. 5 | # All rights reserved. 6 | # 7 | # Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # 10 | # Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer 12 | # in the documentation and/or other materials provided with the 13 | # distribution. 14 | # 15 | # Neither the name of Salesforce.com nor the names of its 16 | # contributors may be used to endorse or promote products 17 | # derived from this software without specific prior written permission. 18 | # 19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 21 | # NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23 | # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 24 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 26 | # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 28 | # IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 29 | # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 30 | # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | ########################################################################## 32 | 33 | ############################################################ 34 | # Unit test for vmstats plugin 35 | ############################################################ 36 | 37 | import os 38 | import sys 39 | import unittest 40 | 41 | from mock import Mock, patch 42 | 43 | import collectd 44 | sys.path.append(os.path.join(os.path.dirname(__file__), "../plugins")) 45 | import vmstats 46 | 47 | PROCFS_VMSTAT = os.path.abspath(os.path.join(os.path.dirname(__file__), 48 | 'mocks/proc_vmstat')) 49 | 50 | # Expected values for verifications 51 | WHITE_LIST = ['nr_free_pages', 'nr_inactive_anon', 'nr_active_anon', 'nr_inactive_file', 'nr_active_file', 'nr_unevictable', 'nr_mlock', 'nr_anon_pages', 'nr_mapped', 'nr_file_pages', 'nr_dirty', 'nr_writeback', 'nr_writeback_temp', 'nr_shmem', 'numa_hit', 'numa_miss', 'numa_foreign', 'numa_interleave', 'numa_local', 'numa_other', 'pgpgin', 'pgpgout', 'pswpin', 'pswpout', 'pgalloc_dma', 'pgalloc_dma32', 'pgalloc_normal', 'pgfault', 'pgmajfault', 'pgsteal_dma', 'pgsteal_dma32', 'pgsteal_normal', 'pgscan_kswapd_dma', 'pgscan_kswapd_dma32', 'pgscan_kswapd_normal', 'pgscan_direct_dma', 'pgscan_direct_dma32', 'pgscan_direct_normal', 'zone_reclaim_failed', 'slabs_scanned', 'kswapd_steal', 'kswapd_inodesteal', 'kswapd_low_wmark_hit_quickly', 'kswapd_high_wmark_hit_quickly', 'kswapd_skip_congestion_wait', 'pageoutrun', 'allocstall', 'pgrotated', 'compact_blocks_moved', 'compact_pages_moved', 'compact_pagemigrate_failed', 'compact_stall', 'compact_fail', 'compact_success', 'htlb_buddy_alloc_success', 'htlb_buddy_alloc_fail'] 52 | 53 | class TestVmstats(unittest.TestCase): 54 | def setUp(self): 55 | vmstats.VMS_FNAME = PROCFS_VMSTAT 56 | 57 | def test_1_vmstats_get_host_type(self): 58 | vmstats.get_host_type() 59 | self.assertTrue(vmstats.host_type is 'other', 'unknown host type') 60 | 61 | def test_2_vmstats_white_list(self): 62 | global WHITE_LIST 63 | vmstats.init_stats_cache() 64 | WHITE_LIST = list(set().union(WHITE_LIST, 65 | vmstats.pgsteal_white_list, 66 | vmstats.pgscank_white_list, 67 | vmstats.pgscand_white_list)) 68 | try: 69 | self.assertTrue(len(vmstats.white_list) > 0, 'at least one metric') 70 | self.assertEqual(vmstats.white_list, WHITE_LIST, 71 | 'white lists parsing error') 72 | except: 73 | print('vmstats.white_list: %s' % (vmstats.white_list)) 74 | print('vmstats.pgsteal_white_list: %s' % (vmstats.pgsteal_white_list)) 75 | print('vmstats.pgscank_white_list: %s' % (vmstats.pgscank_white_list)) 76 | print('vmstats.pgscand_white_list: %s' % (vmstats.pgscand_white_list)) 77 | print('expected: %s' % (WHITE_LIST)) 78 | print('size: %d expected: %d' 79 | % (len(vmstats.white_list), len(WHITE_LIST))) 80 | for i in range(len(WHITE_LIST)): 81 | print('i: %d %s -->> %s' % (i, vmstats.white_list[i], WHITE_LIST[i])) 82 | print('Exception: %s' % (sys.exc_info()[0])) 83 | raise 84 | 85 | @patch('collectd.Values') 86 | def test_3_vmstats_collection(self, collectdValues): 87 | collectdValues.val = Mock() 88 | vmstats.collect_vmstats() 89 | 90 | assert collectdValues.call_count == len(WHITE_LIST) 91 | self.assertTrue(len(vmstats.stats_cache) > 0, 'at least one metric') 92 | 93 | if __name__ == '__main__': 94 | suite = unittest.TestLoader().loadTestsFromTestCase(TestVmstats) 95 | unittest.TextTestRunner(verbosity=2).run(suite) 96 | -------------------------------------------------------------------------------- /tests/zoneinfo_utest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | ########################################################################## 4 | # Copyright (c) 2015, Salesforce.com, Inc. 5 | # All rights reserved. 6 | # 7 | # Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # 10 | # Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer 12 | # in the documentation and/or other materials provided with the 13 | # distribution. 14 | # 15 | # Neither the name of Salesforce.com nor the names of its 16 | # contributors may be used to endorse or promote products 17 | # derived from this software without specific prior written permission. 18 | # 19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 21 | # NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23 | # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 24 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 26 | # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 28 | # IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 29 | # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 30 | # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | ########################################################################## 32 | 33 | ############################################################ 34 | # Unit test for zoneinfo plugin 35 | ############################################################ 36 | 37 | import os 38 | import sys 39 | import unittest 40 | 41 | from mock import Mock, patch 42 | 43 | import collectd 44 | sys.path.append(os.path.join(os.path.dirname(__file__), "../plugins")) 45 | import zoneinfo 46 | 47 | PROCFS_ZONEINFO = os.path.abspath(os.path.join(os.path.dirname(__file__), 48 | 'mocks/proc_zoneinfo')) 49 | 50 | # Expected values for verifications 51 | WHITE_LIST = ['min', 'low', 'high', 'scanned', 'nr_free_pages', 'nr_dirty', 'nr_writeback', 'nr_vmscan_write', 'nr_anon_transparent_hugepages'] 52 | 53 | 54 | class TestBuddyinfo(unittest.TestCase): 55 | def setUp(self): 56 | zoneinfo.ZONEINFO_FNAME = PROCFS_ZONEINFO 57 | 58 | def test_1_zoneinfo_get_host_type(self): 59 | zoneinfo.get_host_type() 60 | self.assertTrue(zoneinfo.host_type is 'other', 'unknown host type') 61 | 62 | def test_2_zoneinfo_white_list(self): 63 | zoneinfo.init_stats_cache() 64 | 65 | self.assertTrue(len(zoneinfo.white_list) > 0, 'at least one metric') 66 | self.assertEqual(zoneinfo.white_list, WHITE_LIST, 67 | 'white lists parsing error') 68 | 69 | @patch('collectd.Values') 70 | def test_3_zoneinfo_collection(self, collectdValues): 71 | collectdValues.vals = Mock() 72 | zoneinfo.collect_zoneinfo() 73 | 74 | collectdValues.assert_called_once() 75 | self.assertTrue(len(zoneinfo.stats_cache) > 0, 'at least one udp counter') 76 | 77 | if __name__ == '__main__': 78 | suite = unittest.TestLoader().loadTestsFromTestCase(TestBuddyinfo) 79 | unittest.TextTestRunner(verbosity=2).run(suite) 80 | --------------------------------------------------------------------------------