├── CHANGELOG.txt ├── LICENSE.txt ├── MANIFEST.in ├── README.txt ├── collectd.py ├── dist ├── collectd-1.0.1.tar.gz └── collectd-1.0.2.tar.gz ├── docs ├── .buildinfo ├── _sources │ └── index.txt ├── _static │ ├── basic.css │ ├── default.css │ ├── doctools.js │ ├── file.png │ ├── jquery.js │ ├── minus.png │ ├── plus.png │ ├── pygments.css │ ├── searchtools.js │ ├── sidebar.js │ └── underscore.js ├── genindex.html ├── index.html ├── objects.inv ├── search.html └── searchindex.js ├── examples ├── basic.py └── primes.py ├── setup.py ├── sphinx ├── Makefile ├── build │ └── doctrees │ │ ├── environment.pickle │ │ └── index.doctree ├── conf.py └── index.rst └── unit_tests.py /CHANGELOG.txt: -------------------------------------------------------------------------------- 1 | 2 | WHAT'S NEW IN 1.0.2 3 | ------------------- 4 | bugfix: Counter.record and Counter.set_exact now accept unicode values 5 | https://github.com/appliedsec/collectd/issues/2 6 | 7 | feature: collectd.__version__ and collectd.__version_info__ are now defined 8 | 9 | 10 | 11 | WHAT'S NEW IN 1.0.1 12 | ------------------- 13 | hosting: collectd is now hosted on Github 14 | https://github.com/appliedsec/collectd 15 | 16 | bugfix: re-instantiating a Connection object causes __init__ to be called again 17 | https://github.com/appliedsec/collectd/issues/1 18 | 19 | feature: plugin name is now settable per Connection, "any" is still the default 20 | (patch provided by Charles Hooper) 21 | https://github.com/appliedsec/collectd/issues/2 22 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) Eli Courtwright and other individual contributors. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of Eli Courtwright nor the names of other contributors 15 | may be used to endorse or promote products derived from this software 16 | without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 22 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.txt LICENSE.txt unit_tests.py 2 | recursive-include docs * 3 | recursive-include examples *.py 4 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | This Python module implements the binary protocol used by the collectd Network 2 | plugin to let you send arbitrary numeric data to collectd servers. Other than 3 | turning on the Network plugin on the destination collectd server, no 4 | configuration is needed. 5 | 6 | Documentation may be found locally in the docs/ directory or online at 7 | http://packages.python.org/collectd/ 8 | -------------------------------------------------------------------------------- /collectd.py: -------------------------------------------------------------------------------- 1 | import re 2 | import time 3 | import socket 4 | import struct 5 | import logging 6 | import traceback 7 | from functools import wraps 8 | from Queue import Queue, Empty 9 | from collections import defaultdict 10 | from threading import RLock, Thread, Semaphore 11 | 12 | 13 | __all__ = ["Connection", "start_threads"] 14 | 15 | __version_info__ = (1, 0, 2, "final", 0) 16 | __version__ = "{0}.{1}.{2}".format(*__version_info__) 17 | 18 | logger = logging.getLogger("collectd") 19 | 20 | SEND_INTERVAL = 10 # seconds 21 | MAX_PACKET_SIZE = 1024 # bytes 22 | 23 | PLUGIN_TYPE = "gauge" 24 | 25 | TYPE_HOST = 0x0000 26 | TYPE_TIME = 0x0001 27 | TYPE_PLUGIN = 0x0002 28 | TYPE_PLUGIN_INSTANCE = 0x0003 29 | TYPE_TYPE = 0x0004 30 | TYPE_TYPE_INSTANCE = 0x0005 31 | TYPE_VALUES = 0x0006 32 | TYPE_INTERVAL = 0x0007 33 | LONG_INT_CODES = [TYPE_TIME, TYPE_INTERVAL] 34 | STRING_CODES = [TYPE_HOST, TYPE_PLUGIN, TYPE_PLUGIN_INSTANCE, TYPE_TYPE, TYPE_TYPE_INSTANCE] 35 | 36 | VALUE_COUNTER = 0 37 | VALUE_GAUGE = 1 38 | VALUE_DERIVE = 2 39 | VALUE_ABSOLUTE = 3 40 | VALUE_CODES = { 41 | VALUE_COUNTER: "!Q", 42 | VALUE_GAUGE: " MAX_PACKET_SIZE: 90 | packets.append("".join(curr)) 91 | curr, curr_len = [start], len(start) 92 | curr.append(part) 93 | curr_len += len(part) 94 | packets.append("".join(curr)) 95 | return packets 96 | 97 | 98 | 99 | def sanitize(s): 100 | return re.sub(r"[^a-zA-Z0-9]+", "_", s).strip("_") 101 | 102 | def swallow_errors(func): 103 | @wraps(func) 104 | def wrapped(*args, **kwargs): 105 | try: 106 | return func(*args, **kwargs) 107 | except: 108 | try: 109 | logger.error("unexpected error", exc_info = True) 110 | except: 111 | pass 112 | return wrapped 113 | 114 | def synchronized(method): 115 | @wraps(method) 116 | def wrapped(self, *args, **kwargs): 117 | with self._lock: 118 | return method(self, *args, **kwargs) 119 | return wrapped 120 | 121 | class Counter(object): 122 | def __init__(self, category): 123 | self.category = category 124 | self._lock = RLock() 125 | self.counts = defaultdict(lambda: defaultdict(float)) 126 | 127 | @swallow_errors 128 | @synchronized 129 | def record(self, *args, **kwargs): 130 | for specific in list(args) + [""]: 131 | assert isinstance(specific, basestring) 132 | for stat, value in kwargs.items(): 133 | assert isinstance(value, (int, float)) 134 | self.counts[str(specific)][str(stat)] += value 135 | 136 | @swallow_errors 137 | @synchronized 138 | def set_exact(self, **kwargs): 139 | for stat, value in kwargs.items(): 140 | assert isinstance(value, (int, float)) 141 | self.counts[""][str(stat)] = value 142 | 143 | @synchronized 144 | def snapshot(self): 145 | totals = {} 146 | for specific,counts in self.counts.items(): 147 | for stat in counts: 148 | name_parts = map(sanitize, [self.category, specific, stat]) 149 | name = "-".join(name_parts).replace("--", "-") 150 | totals[name] = counts[stat] 151 | counts[stat] = 0.0 152 | return totals 153 | 154 | class Connection(object): 155 | _lock = RLock() # class-level lock, only used for __new__ 156 | instances = {} 157 | 158 | @synchronized 159 | def __new__(cls, hostname = socket.gethostname(), 160 | collectd_host = "localhost", collectd_port = 25826, 161 | plugin_inst = "", plugin_name = "any"): 162 | id = (hostname, collectd_host, collectd_port, plugin_inst, plugin_name) 163 | if id in cls.instances: 164 | return cls.instances[id] 165 | else: 166 | inst = object.__new__(cls) 167 | cls.instances[id] = inst 168 | return inst 169 | 170 | def __init__(self, hostname = socket.gethostname(), 171 | collectd_host = "localhost", collectd_port = 25826, 172 | plugin_inst = "", plugin_name = "any"): 173 | if "_counters" not in self.__dict__: 174 | self._lock = RLock() 175 | self._counters = {} 176 | self._plugin_inst = plugin_inst 177 | self._plugin_name = plugin_name 178 | self._hostname = hostname 179 | self._collectd_addr = (collectd_host, collectd_port) 180 | 181 | @synchronized 182 | def __getattr__(self, name): 183 | if name.startswith("_"): 184 | raise AttributeError("{0} object has no attribute {1!r}".format(self.__class__.__name__, name)) 185 | 186 | if name not in self._counters: 187 | self._counters[name] = Counter(name) 188 | return self._counters[name] 189 | 190 | @synchronized 191 | def _snapshot(self): 192 | return [c.snapshot() for c in self._counters.values() if c.counts] 193 | 194 | 195 | 196 | snaps = Queue() 197 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 198 | 199 | def take_snapshots(): 200 | for conn in Connection.instances.values(): 201 | snapshots = conn._snapshot() 202 | if snapshots: 203 | stats = {} 204 | for snapshot in snapshots: 205 | stats.update(snapshot) 206 | snaps.put([int(time.time()), stats, conn]) 207 | 208 | def send_stats(raise_on_empty = False): 209 | try: 210 | when, stats, conn = snaps.get(timeout = 0.1) 211 | for message in messages(stats, when, conn._hostname, conn._plugin_inst, conn._plugin_name): 212 | sock.sendto(message, conn._collectd_addr) 213 | except Empty: 214 | if raise_on_empty: 215 | raise 216 | 217 | def daemonize(func, sleep_for = 0): 218 | @wraps(func) 219 | def wrapped(): 220 | while True: 221 | try: 222 | func() 223 | except: 224 | try: 225 | logger.error("unexpected error", exc_info = True) 226 | except: 227 | traceback.print_exc() 228 | time.sleep(sleep_for) 229 | 230 | t = Thread(target = wrapped) 231 | t.daemon = True 232 | t.start() 233 | 234 | single_start = Semaphore() 235 | def start_threads(): 236 | assert single_start.acquire(blocking = False) 237 | daemonize(take_snapshots, sleep_for = SEND_INTERVAL) 238 | daemonize(send_stats) 239 | -------------------------------------------------------------------------------- /dist/collectd-1.0.1.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appliedsec/collectd/7b51edfd08e055149b446e9839c4dc0bc7c834ce/dist/collectd-1.0.1.tar.gz -------------------------------------------------------------------------------- /dist/collectd-1.0.2.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appliedsec/collectd/7b51edfd08e055149b446e9839c4dc0bc7c834ce/dist/collectd-1.0.2.tar.gz -------------------------------------------------------------------------------- /docs/.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: b152c99d1b53df289c844bb312cc7c8d 4 | tags: fbb0d17656682115ca4d033fb2f83ba1 5 | -------------------------------------------------------------------------------- /docs/_sources/index.txt: -------------------------------------------------------------------------------- 1 | .. toctree:: 2 | :maxdepth: 1 3 | 4 | 5 | collectd - Send statistics over UDP to collectd servers 6 | ======================================================= 7 | 8 | This module implements the 9 | `binary protocol `_ 10 | used by the 11 | `Network plugin `_ 12 | to let you send arbitrary numeric data to collectd servers. Other than turning 13 | on the Network plugin on the destination collectd server, no configuration is 14 | needed. 15 | 16 | Although you can configure your collectd server to do anything with your 17 | statistics, most people use the 18 | `RRDtool plugin `_ 19 | to efficiently store large quantities of data. Therefore, this tutorial 20 | will discuss the output files generated by the RRDtool plugin, even though 21 | this module sends destination-agnostic statistics messages to your collectd 22 | server. 23 | 24 | Here's an example of sending statistics: 25 | 26 | .. literalinclude:: ../examples/basic.py 27 | 28 | If you run this script (which is ``examples/basic.py`` in your source package) 29 | then your collectd server will create an RRD file for each statistic you are 30 | tracking. These files are typically stored under one central location on the 31 | filesysem, such as ``/var/lib/collectd/rrd`` and organized by the hostname of 32 | where the statistics came from and the name of the plugin that generated them. 33 | 34 | This module identifies itself with the plugin name ``any``, so if you ran 35 | the above script, it would create a ``localhost/any`` directory with the 36 | following files: 37 | 38 | * ``gauge-some_category-another_stat.rrd`` 39 | * ``gauge-some_category-some_counter.rrd`` 40 | * ``gauge-coin_stats-heads-flips.rrd`` 41 | * ``gauge-coin_stats-tails-flips.rrd`` 42 | * ``gauge-coin_stats-flips.rrd`` (contains the sum of heads and tails flips) 43 | 44 | Each call to ``record()`` increments the statistics you provide. Periodically 45 | the sums of these statistics are sent to the collectd server and then reset. 46 | Therefore, if you displayed a graph of one of these statistics files, each 47 | data point on the graph would represent the sum of all ``record()`` values 48 | over that time increment. 49 | 50 | 51 | 52 | Installation 53 | ============ 54 | This module is free for use under the BSD license. It requires Python 2.6 or 55 | Python 2.7 and has no other dependencies. 56 | 57 | You may `click here `_ 58 | to download the collectd module. You may also run ``easy_install collectd`` 59 | if you have `EasyInstall `_ 60 | on your system. The project page for collectd in the Cheese Shop (aka the Python 61 | Package Index or PyPI) `may be found here `_. 62 | 63 | You may also check out the development version of collectd with this command: 64 | 65 | ``git clone https://github.com/appliedsec/collectd.git`` 66 | 67 | 68 | Functions and Classes 69 | ===================== 70 | 71 | .. function:: start_threads() 72 | 73 | This function starts two daemon threads. The first takes snapshots of your 74 | counters and resets them periodically. The other serializes the statistics 75 | into protocol messages understood by the collectd Network plugin and sends 76 | them in appropriately-sized UDP packets. 77 | 78 | You must call this function when your program starts, or else this module 79 | will never actually send any data to any collectd servers. Calling this 80 | function more than once throws an exception. 81 | 82 | 83 | 84 | .. class:: Connection(hostname = socket.gethostname(), collectd_host = "localhost", collectd_port = 25826, plugin_inst = "", plugin_name = "any") 85 | 86 | Connection objects may be instantiated with 5 optional arguments: 87 | 88 | * ``hostname``: the hostname you use to identify yourself to the collectd server; if omitted, this defaults to the result of ``socket.gethostname()`` 89 | * ``collectd_host``: the hostname or ip address of the collectd server to which we will send statistics 90 | * ``collectd_port``: the port to which you will send statistics messages 91 | * ``plugin_inst``: the plugin instance name which will be sent to the collectd server; this mostly affects the directory name used by the collectd rrdtool plugin 92 | * ``plugin_name``: the name of the plugin with which the collectd server will associate your statistics; this mostly affects the directory tree used by the collectd rrdtool plugin 93 | 94 | Connection objects with identical parameters are singletons; in other 95 | words, ``Connection("foo") is Connection("foo")`` but 96 | ``Connection("foo") is not Connection("bar")``. 97 | 98 | .. method:: __getattr__(name) 99 | 100 | Statistics are recorded through ``Counter`` objects, which are 101 | dynamically generated by accessing fields on ``Connection`` instances. 102 | So saying ``conn.foo`` creates a ``Counter`` object. 103 | 104 | These objects are distinct but cached, so ``conn.foo is conn.foo`` but 105 | ``conn.foo is not conn.bar``. 106 | 107 | 108 | 109 | .. class:: Counter(category) 110 | 111 | You shouldn't directly instantiate this class; instead ``Counter`` objects 112 | are automatically created by accessing attributes of ``Connection`` objects 113 | such that ``conn.foo`` will cache and return ``Counter("foo")``. 114 | 115 | Both of the following methods swallow and log all possible exceptions, so 116 | you never need to worry about an error being thrown by calls to either of 117 | these methods. These functions are also synchronized, so you can safely 118 | call them simultaneously from different threads. 119 | 120 | .. method:: record(*specific, **stats) 121 | 122 | Each keyword argument to this method is interpreted as a statistic, 123 | whose name is the argument name, and whose value is incrementd by 124 | the argument value. 125 | 126 | You may pass one or more string identifiers as positional arguments 127 | to this method. If you do so, then separate statistic counts will 128 | be maintained for this identifier. These counts are always added 129 | to the base count for each statistic. 130 | 131 | For example, if you ran the following code 132 | 133 | .. code-block:: python 134 | 135 | conn = collectd.Connection() 136 | conn.example.record(baz = 1) 137 | conn.example.record("foo", baz = 2) 138 | conn.example.record("bar", baz = 3) 139 | 140 | and then statistics were sent to the collectd server, it would result 141 | in the following files: 142 | 143 | * ``gauge-example-baz.rrd`` (with a value of 6 for this time increment) 144 | * ``gauge-example-foo-baz.rrd`` (with a value of 2 for this time increment) 145 | * ``gauge-example-bar-baz.rrd`` (with a value of 3 for this time increment) 146 | 147 | 148 | .. method:: set_exact(**stats) 149 | 150 | Each keyword argument to this method is interpreted as a statistic, 151 | whose name is the argument name, and whose value is set to the exact 152 | value of the argument. Use this method when you have values which you 153 | wish to update to a specific value rather than increment. 154 | 155 | 156 | 157 | .. warning:: 158 | 159 | All names are sanitized to contain only alphanumeric characters separated 160 | by underscores. In other words, if you did something like 161 | 162 | .. code-block:: python 163 | 164 | conn = collectd.Connection() 165 | counter = getattr(conn, "^@#@foo%$&&*") 166 | stat = {"*()#@spam!@$^&*": 1} 167 | counter.record("()#@bar&*()baz$^_+", **stat) 168 | 169 | then the resulting files would be named ``gauge-foo-spam.rrd`` and 170 | ``gauge-foo-bar_baz-spam.rrd``. Although this behavior is generally 171 | desirable, it could lead to your statistics becoming merged. For example, 172 | the ``foo-bar`` and ``foo/bar`` statistics in the following code would be 173 | combined into a single ``foo_bar`` statistic: 174 | 175 | .. code-block:: python 176 | 177 | conn = collectd.Connection() 178 | conn.foo.record("foo-bar", baz = 2) 179 | conn.foo.record("foo/bar", baz = 3) 180 | 181 | 182 | 183 | Logging 184 | ======= 185 | As mentioned above, collectd swallows exceptions so that you never have to 186 | worry about calling a function from this module and triggering an exception. 187 | However, any exceptions which do occur are logged using the 188 | `logging `_ module from the 189 | standard library, specifically to the `collectd` logger. No other logging 190 | is performed. 191 | 192 | However, this module defines no handlers for the `collectd` logger, so by 193 | default nothing is done with any of these log messages. 194 | 195 | 196 | 197 | A More Complex Example 198 | ====================== 199 | The following code is available in the ``examples/primes.py`` file in your 200 | source distribution: 201 | 202 | .. literalinclude:: ../examples/primes.py 203 | 204 | Here's a list of files generated by this code, along with an explanation of 205 | the counter which each file contains for each time interval: 206 | 207 | * ``gauge-queue-size.rrd``: a snapshot of the size of the numbers queue 208 | * ``gauge-producer-too_small.rrd``: a count of the random numbers generated by the producer thread which were discarded for being too small 209 | * ``gauge-producer-too_big.rrd``: a count of the random numbers generated by the producer thread which were discarded for being too large 210 | * ``gauge-producer-just_right.rrd``: a count of the random numbers generated by the producer thread which were sent to the consumer thread for factoring 211 | * ``gauge-consumer-count.rrd``: an overall count of the numbers factored by the consumer thread 212 | * ``gauge-consumer-composite-count.rrd``: a count of the numbers factored by the consumer thread which turned out to be non-prime 213 | * ``gauge-consumer-prime-count.rrd``: a count of the numbers factored by the consumer thread which turned out to be prime 214 | * ``gauge-consumer-time.rrd``: the amount of wallclock time elapsed while factoring numbers 215 | * ``gauge-consumer-composite-time.rrd``: the amount of wallclock time elapsed while factoring numbers which turned out to be non-prime 216 | * ``gauge-consumer-prime-time.rrd``: the amount of wallclock time elapsed while factoring numbers which turned out to be prime 217 | 218 | TODO: add graphs to this example to demonstrate what the data looks like 219 | 220 | 221 | 222 | A Utility for Graphing RRD Data 223 | =============================== 224 | This is forthcoming; we'd like a simple script for generating the complex 225 | command-line arguments understood by ``rrdtool graph`` commands. 226 | 227 | At some point we may also want a web interface similar to the existing 228 | collectd cgi script which dynamically lets you select and generate graphs, 229 | but with awareness of the semantics of the files generated by this module, 230 | which would allow users to start with a high-level overview and drill-down 231 | into specific data, combine data from different sources into one graph, etc. 232 | -------------------------------------------------------------------------------- /docs/_static/basic.css: -------------------------------------------------------------------------------- 1 | /* 2 | * basic.css 3 | * ~~~~~~~~~ 4 | * 5 | * Sphinx stylesheet -- basic theme. 6 | * 7 | * :copyright: Copyright 2007-2010 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 | img { 83 | border: 0; 84 | } 85 | 86 | /* -- search page ----------------------------------------------------------- */ 87 | 88 | ul.search { 89 | margin: 10px 0 0 20px; 90 | padding: 0; 91 | } 92 | 93 | ul.search li { 94 | padding: 5px 0 5px 20px; 95 | background-image: url(file.png); 96 | background-repeat: no-repeat; 97 | background-position: 0 7px; 98 | } 99 | 100 | ul.search li a { 101 | font-weight: bold; 102 | } 103 | 104 | ul.search li div.context { 105 | color: #888; 106 | margin: 2px 0 0 30px; 107 | text-align: left; 108 | } 109 | 110 | ul.keywordmatches li.goodmatch a { 111 | font-weight: bold; 112 | } 113 | 114 | /* -- index page ------------------------------------------------------------ */ 115 | 116 | table.contentstable { 117 | width: 90%; 118 | } 119 | 120 | table.contentstable p.biglink { 121 | line-height: 150%; 122 | } 123 | 124 | a.biglink { 125 | font-size: 1.3em; 126 | } 127 | 128 | span.linkdescr { 129 | font-style: italic; 130 | padding-top: 5px; 131 | font-size: 90%; 132 | } 133 | 134 | /* -- general index --------------------------------------------------------- */ 135 | 136 | table.indextable { 137 | width: 100%; 138 | } 139 | 140 | table.indextable td { 141 | text-align: left; 142 | vertical-align: top; 143 | } 144 | 145 | table.indextable dl, table.indextable dd { 146 | margin-top: 0; 147 | margin-bottom: 0; 148 | } 149 | 150 | table.indextable tr.pcap { 151 | height: 10px; 152 | } 153 | 154 | table.indextable tr.cap { 155 | margin-top: 10px; 156 | background-color: #f2f2f2; 157 | } 158 | 159 | img.toggler { 160 | margin-right: 3px; 161 | margin-top: 3px; 162 | cursor: pointer; 163 | } 164 | 165 | div.modindex-jumpbox { 166 | border-top: 1px solid #ddd; 167 | border-bottom: 1px solid #ddd; 168 | margin: 1em 0 1em 0; 169 | padding: 0.4em; 170 | } 171 | 172 | div.genindex-jumpbox { 173 | border-top: 1px solid #ddd; 174 | border-bottom: 1px solid #ddd; 175 | margin: 1em 0 1em 0; 176 | padding: 0.4em; 177 | } 178 | 179 | /* -- general body styles --------------------------------------------------- */ 180 | 181 | a.headerlink { 182 | visibility: hidden; 183 | } 184 | 185 | h1:hover > a.headerlink, 186 | h2:hover > a.headerlink, 187 | h3:hover > a.headerlink, 188 | h4:hover > a.headerlink, 189 | h5:hover > a.headerlink, 190 | h6:hover > a.headerlink, 191 | dt:hover > a.headerlink { 192 | visibility: visible; 193 | } 194 | 195 | div.body p.caption { 196 | text-align: inherit; 197 | } 198 | 199 | div.body td { 200 | text-align: left; 201 | } 202 | 203 | .field-list ul { 204 | padding-left: 1em; 205 | } 206 | 207 | .first { 208 | margin-top: 0 !important; 209 | } 210 | 211 | p.rubric { 212 | margin-top: 30px; 213 | font-weight: bold; 214 | } 215 | 216 | .align-left { 217 | text-align: left; 218 | } 219 | 220 | .align-center { 221 | clear: both; 222 | text-align: center; 223 | } 224 | 225 | .align-right { 226 | text-align: right; 227 | } 228 | 229 | /* -- sidebars -------------------------------------------------------------- */ 230 | 231 | div.sidebar { 232 | margin: 0 0 0.5em 1em; 233 | border: 1px solid #ddb; 234 | padding: 7px 7px 0 7px; 235 | background-color: #ffe; 236 | width: 40%; 237 | float: right; 238 | } 239 | 240 | p.sidebar-title { 241 | font-weight: bold; 242 | } 243 | 244 | /* -- topics ---------------------------------------------------------------- */ 245 | 246 | div.topic { 247 | border: 1px solid #ccc; 248 | padding: 7px 7px 0 7px; 249 | margin: 10px 0 10px 0; 250 | } 251 | 252 | p.topic-title { 253 | font-size: 1.1em; 254 | font-weight: bold; 255 | margin-top: 10px; 256 | } 257 | 258 | /* -- admonitions ----------------------------------------------------------- */ 259 | 260 | div.admonition { 261 | margin-top: 10px; 262 | margin-bottom: 10px; 263 | padding: 7px; 264 | } 265 | 266 | div.admonition dt { 267 | font-weight: bold; 268 | } 269 | 270 | div.admonition dl { 271 | margin-bottom: 0; 272 | } 273 | 274 | p.admonition-title { 275 | margin: 0px 10px 5px 0px; 276 | font-weight: bold; 277 | } 278 | 279 | div.body p.centered { 280 | text-align: center; 281 | margin-top: 25px; 282 | } 283 | 284 | /* -- tables ---------------------------------------------------------------- */ 285 | 286 | table.docutils { 287 | border: 0; 288 | border-collapse: collapse; 289 | } 290 | 291 | table.docutils td, table.docutils th { 292 | padding: 1px 8px 1px 5px; 293 | border-top: 0; 294 | border-left: 0; 295 | border-right: 0; 296 | border-bottom: 1px solid #aaa; 297 | } 298 | 299 | table.field-list td, table.field-list th { 300 | border: 0 !important; 301 | } 302 | 303 | table.footnote td, table.footnote th { 304 | border: 0 !important; 305 | } 306 | 307 | th { 308 | text-align: left; 309 | padding-right: 5px; 310 | } 311 | 312 | table.citation { 313 | border-left: solid 1px gray; 314 | margin-left: 1px; 315 | } 316 | 317 | table.citation td { 318 | border-bottom: none; 319 | } 320 | 321 | /* -- other body styles ----------------------------------------------------- */ 322 | 323 | ol.arabic { 324 | list-style: decimal; 325 | } 326 | 327 | ol.loweralpha { 328 | list-style: lower-alpha; 329 | } 330 | 331 | ol.upperalpha { 332 | list-style: upper-alpha; 333 | } 334 | 335 | ol.lowerroman { 336 | list-style: lower-roman; 337 | } 338 | 339 | ol.upperroman { 340 | list-style: upper-roman; 341 | } 342 | 343 | dl { 344 | margin-bottom: 15px; 345 | } 346 | 347 | dd p { 348 | margin-top: 0px; 349 | } 350 | 351 | dd ul, dd table { 352 | margin-bottom: 10px; 353 | } 354 | 355 | dd { 356 | margin-top: 3px; 357 | margin-bottom: 10px; 358 | margin-left: 30px; 359 | } 360 | 361 | dt:target, .highlighted { 362 | background-color: #fbe54e; 363 | } 364 | 365 | dl.glossary dt { 366 | font-weight: bold; 367 | font-size: 1.1em; 368 | } 369 | 370 | .field-list ul { 371 | margin: 0; 372 | padding-left: 1em; 373 | } 374 | 375 | .field-list p { 376 | margin: 0; 377 | } 378 | 379 | .refcount { 380 | color: #060; 381 | } 382 | 383 | .optional { 384 | font-size: 1.3em; 385 | } 386 | 387 | .versionmodified { 388 | font-style: italic; 389 | } 390 | 391 | .system-message { 392 | background-color: #fda; 393 | padding: 5px; 394 | border: 3px solid red; 395 | } 396 | 397 | .footnote:target { 398 | background-color: #ffa 399 | } 400 | 401 | .line-block { 402 | display: block; 403 | margin-top: 1em; 404 | margin-bottom: 1em; 405 | } 406 | 407 | .line-block .line-block { 408 | margin-top: 0; 409 | margin-bottom: 0; 410 | margin-left: 1.5em; 411 | } 412 | 413 | .guilabel, .menuselection { 414 | font-family: sans-serif; 415 | } 416 | 417 | .accelerator { 418 | text-decoration: underline; 419 | } 420 | 421 | .classifier { 422 | font-style: oblique; 423 | } 424 | 425 | /* -- code displays --------------------------------------------------------- */ 426 | 427 | pre { 428 | overflow: auto; 429 | } 430 | 431 | td.linenos pre { 432 | padding: 5px 0px; 433 | border: 0; 434 | background-color: transparent; 435 | color: #aaa; 436 | } 437 | 438 | table.highlighttable { 439 | margin-left: 0.5em; 440 | } 441 | 442 | table.highlighttable td { 443 | padding: 0 0.5em 0 0.5em; 444 | } 445 | 446 | tt.descname { 447 | background-color: transparent; 448 | font-weight: bold; 449 | font-size: 1.2em; 450 | } 451 | 452 | tt.descclassname { 453 | background-color: transparent; 454 | } 455 | 456 | tt.xref, a tt { 457 | background-color: transparent; 458 | font-weight: bold; 459 | } 460 | 461 | h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt { 462 | background-color: transparent; 463 | } 464 | 465 | .viewcode-link { 466 | float: right; 467 | } 468 | 469 | .viewcode-back { 470 | float: right; 471 | font-family: sans-serif; 472 | } 473 | 474 | div.viewcode-block:target { 475 | margin: -1px -10px; 476 | padding: 0 10px; 477 | } 478 | 479 | /* -- math display ---------------------------------------------------------- */ 480 | 481 | img.math { 482 | vertical-align: middle; 483 | } 484 | 485 | div.body div.math p { 486 | text-align: center; 487 | } 488 | 489 | span.eqno { 490 | float: right; 491 | } 492 | 493 | /* -- printout stylesheet --------------------------------------------------- */ 494 | 495 | @media print { 496 | div.document, 497 | div.documentwrapper, 498 | div.bodywrapper { 499 | margin: 0 !important; 500 | width: 100%; 501 | } 502 | 503 | div.sphinxsidebar, 504 | div.related, 505 | div.footer, 506 | #top-link { 507 | display: none; 508 | } 509 | } 510 | -------------------------------------------------------------------------------- /docs/_static/default.css: -------------------------------------------------------------------------------- 1 | /* 2 | * default.css_t 3 | * ~~~~~~~~~~~~~ 4 | * 5 | * Sphinx stylesheet -- default theme. 6 | * 7 | * :copyright: Copyright 2007-2010 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 | /* -- hyperlink styles ------------------------------------------------------ */ 118 | 119 | a { 120 | color: #355f7c; 121 | text-decoration: none; 122 | } 123 | 124 | a:visited { 125 | color: #355f7c; 126 | text-decoration: none; 127 | } 128 | 129 | a:hover { 130 | text-decoration: underline; 131 | } 132 | 133 | 134 | 135 | /* -- body styles ----------------------------------------------------------- */ 136 | 137 | div.body h1, 138 | div.body h2, 139 | div.body h3, 140 | div.body h4, 141 | div.body h5, 142 | div.body h6 { 143 | font-family: 'Trebuchet MS', sans-serif; 144 | background-color: #f2f2f2; 145 | font-weight: normal; 146 | color: #20435c; 147 | border-bottom: 1px solid #ccc; 148 | margin: 20px -20px 10px -20px; 149 | padding: 3px 0 3px 10px; 150 | } 151 | 152 | div.body h1 { margin-top: 0; font-size: 200%; } 153 | div.body h2 { font-size: 160%; } 154 | div.body h3 { font-size: 140%; } 155 | div.body h4 { font-size: 120%; } 156 | div.body h5 { font-size: 110%; } 157 | div.body h6 { font-size: 100%; } 158 | 159 | a.headerlink { 160 | color: #c60f0f; 161 | font-size: 0.8em; 162 | padding: 0 4px 0 4px; 163 | text-decoration: none; 164 | } 165 | 166 | a.headerlink:hover { 167 | background-color: #c60f0f; 168 | color: white; 169 | } 170 | 171 | div.body p, div.body dd, div.body li { 172 | text-align: justify; 173 | line-height: 130%; 174 | } 175 | 176 | div.admonition p.admonition-title + p { 177 | display: inline; 178 | } 179 | 180 | div.admonition p { 181 | margin-bottom: 5px; 182 | } 183 | 184 | div.admonition pre { 185 | margin-bottom: 5px; 186 | } 187 | 188 | div.admonition ul, div.admonition ol { 189 | margin-bottom: 5px; 190 | } 191 | 192 | div.note { 193 | background-color: #eee; 194 | border: 1px solid #ccc; 195 | } 196 | 197 | div.seealso { 198 | background-color: #ffc; 199 | border: 1px solid #ff6; 200 | } 201 | 202 | div.topic { 203 | background-color: #eee; 204 | } 205 | 206 | div.warning { 207 | background-color: #ffe4e4; 208 | border: 1px solid #f66; 209 | } 210 | 211 | p.admonition-title { 212 | display: inline; 213 | } 214 | 215 | p.admonition-title:after { 216 | content: ":"; 217 | } 218 | 219 | pre { 220 | padding: 5px; 221 | background-color: #eeffcc; 222 | color: #333333; 223 | line-height: 120%; 224 | border: 1px solid #ac9; 225 | border-left: none; 226 | border-right: none; 227 | } 228 | 229 | tt { 230 | background-color: #ecf0f3; 231 | padding: 0 1px 0 1px; 232 | font-size: 0.95em; 233 | } 234 | 235 | th { 236 | background-color: #ede; 237 | } 238 | 239 | .warning tt { 240 | background: #efc2c2; 241 | } 242 | 243 | .note tt { 244 | background: #d6d6d6; 245 | } 246 | 247 | .viewcode-back { 248 | font-family: sans-serif; 249 | } 250 | 251 | div.viewcode-block:target { 252 | background-color: #f4debf; 253 | border-top: 1px solid #ac9; 254 | border-bottom: 1px solid #ac9; 255 | } -------------------------------------------------------------------------------- /docs/_static/doctools.js: -------------------------------------------------------------------------------- 1 | /* 2 | * doctools.js 3 | * ~~~~~~~~~~~ 4 | * 5 | * Sphinx JavaScript utilties for all documentation. 6 | * 7 | * :copyright: Copyright 2007-2010 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($('.sidebar .this-page-menu')); 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 | $('.sidebar .this-page-menu li.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/_static/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appliedsec/collectd/7b51edfd08e055149b446e9839c4dc0bc7c834ce/docs/_static/file.png -------------------------------------------------------------------------------- /docs/_static/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appliedsec/collectd/7b51edfd08e055149b446e9839c4dc0bc7c834ce/docs/_static/minus.png -------------------------------------------------------------------------------- /docs/_static/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appliedsec/collectd/7b51edfd08e055149b446e9839c4dc0bc7c834ce/docs/_static/plus.png -------------------------------------------------------------------------------- /docs/_static/pygments.css: -------------------------------------------------------------------------------- 1 | .hll { background-color: #ffffcc } 2 | .c { color: #408090; font-style: italic } /* Comment */ 3 | .err { border: 1px solid #FF0000 } /* Error */ 4 | .k { color: #007020; font-weight: bold } /* Keyword */ 5 | .o { color: #666666 } /* Operator */ 6 | .cm { color: #408090; font-style: italic } /* Comment.Multiline */ 7 | .cp { color: #007020 } /* Comment.Preproc */ 8 | .c1 { color: #408090; font-style: italic } /* Comment.Single */ 9 | .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */ 10 | .gd { color: #A00000 } /* Generic.Deleted */ 11 | .ge { font-style: italic } /* Generic.Emph */ 12 | .gr { color: #FF0000 } /* Generic.Error */ 13 | .gh { color: #000080; font-weight: bold } /* Generic.Heading */ 14 | .gi { color: #00A000 } /* Generic.Inserted */ 15 | .go { color: #303030 } /* Generic.Output */ 16 | .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ 17 | .gs { font-weight: bold } /* Generic.Strong */ 18 | .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ 19 | .gt { color: #0040D0 } /* Generic.Traceback */ 20 | .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ 21 | .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ 22 | .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ 23 | .kp { color: #007020 } /* Keyword.Pseudo */ 24 | .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ 25 | .kt { color: #902000 } /* Keyword.Type */ 26 | .m { color: #208050 } /* Literal.Number */ 27 | .s { color: #4070a0 } /* Literal.String */ 28 | .na { color: #4070a0 } /* Name.Attribute */ 29 | .nb { color: #007020 } /* Name.Builtin */ 30 | .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ 31 | .no { color: #60add5 } /* Name.Constant */ 32 | .nd { color: #555555; font-weight: bold } /* Name.Decorator */ 33 | .ni { color: #d55537; font-weight: bold } /* Name.Entity */ 34 | .ne { color: #007020 } /* Name.Exception */ 35 | .nf { color: #06287e } /* Name.Function */ 36 | .nl { color: #002070; font-weight: bold } /* Name.Label */ 37 | .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ 38 | .nt { color: #062873; font-weight: bold } /* Name.Tag */ 39 | .nv { color: #bb60d5 } /* Name.Variable */ 40 | .ow { color: #007020; font-weight: bold } /* Operator.Word */ 41 | .w { color: #bbbbbb } /* Text.Whitespace */ 42 | .mf { color: #208050 } /* Literal.Number.Float */ 43 | .mh { color: #208050 } /* Literal.Number.Hex */ 44 | .mi { color: #208050 } /* Literal.Number.Integer */ 45 | .mo { color: #208050 } /* Literal.Number.Oct */ 46 | .sb { color: #4070a0 } /* Literal.String.Backtick */ 47 | .sc { color: #4070a0 } /* Literal.String.Char */ 48 | .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ 49 | .s2 { color: #4070a0 } /* Literal.String.Double */ 50 | .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ 51 | .sh { color: #4070a0 } /* Literal.String.Heredoc */ 52 | .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ 53 | .sx { color: #c65d09 } /* Literal.String.Other */ 54 | .sr { color: #235388 } /* Literal.String.Regex */ 55 | .s1 { color: #4070a0 } /* Literal.String.Single */ 56 | .ss { color: #517918 } /* Literal.String.Symbol */ 57 | .bp { color: #007020 } /* Name.Builtin.Pseudo */ 58 | .vc { color: #bb60d5 } /* Name.Variable.Class */ 59 | .vg { color: #bb60d5 } /* Name.Variable.Global */ 60 | .vi { color: #bb60d5 } /* Name.Variable.Instance */ 61 | .il { color: #208050 } /* Literal.Number.Integer.Long */ -------------------------------------------------------------------------------- /docs/_static/searchtools.js: -------------------------------------------------------------------------------- 1 | /* 2 | * searchtools.js 3 | * ~~~~~~~~~~~~~~ 4 | * 5 | * Sphinx JavaScript utilties for the full-text search. 6 | * 7 | * :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | /** 13 | * helper function to return a node containing the 14 | * search summary for a given text. keywords is a list 15 | * of stemmed words, hlwords is the list of normal, unstemmed 16 | * words. the first one is used to find the occurance, the 17 | * latter for highlighting it. 18 | */ 19 | 20 | jQuery.makeSearchSummary = function(text, keywords, hlwords) { 21 | var textLower = text.toLowerCase(); 22 | var start = 0; 23 | $.each(keywords, function() { 24 | var i = textLower.indexOf(this.toLowerCase()); 25 | if (i > -1) 26 | start = i; 27 | }); 28 | start = Math.max(start - 120, 0); 29 | var excerpt = ((start > 0) ? '...' : '') + 30 | $.trim(text.substr(start, 240)) + 31 | ((start + 240 - text.length) ? '...' : ''); 32 | var rv = $('
').text(excerpt); 33 | $.each(hlwords, function() { 34 | rv = rv.highlightText(this, 'highlighted'); 35 | }); 36 | return rv; 37 | } 38 | 39 | /** 40 | * Porter Stemmer 41 | */ 42 | var PorterStemmer = function() { 43 | 44 | var step2list = { 45 | ational: 'ate', 46 | tional: 'tion', 47 | enci: 'ence', 48 | anci: 'ance', 49 | izer: 'ize', 50 | bli: 'ble', 51 | alli: 'al', 52 | entli: 'ent', 53 | eli: 'e', 54 | ousli: 'ous', 55 | ization: 'ize', 56 | ation: 'ate', 57 | ator: 'ate', 58 | alism: 'al', 59 | iveness: 'ive', 60 | fulness: 'ful', 61 | ousness: 'ous', 62 | aliti: 'al', 63 | iviti: 'ive', 64 | biliti: 'ble', 65 | logi: 'log' 66 | }; 67 | 68 | var step3list = { 69 | icate: 'ic', 70 | ative: '', 71 | alize: 'al', 72 | iciti: 'ic', 73 | ical: 'ic', 74 | ful: '', 75 | ness: '' 76 | }; 77 | 78 | var c = "[^aeiou]"; // consonant 79 | var v = "[aeiouy]"; // vowel 80 | var C = c + "[^aeiouy]*"; // consonant sequence 81 | var V = v + "[aeiou]*"; // vowel sequence 82 | 83 | var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 84 | var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 85 | var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 86 | var s_v = "^(" + C + ")?" + v; // vowel in stem 87 | 88 | this.stemWord = function (w) { 89 | var stem; 90 | var suffix; 91 | var firstch; 92 | var origword = w; 93 | 94 | if (w.length < 3) 95 | return w; 96 | 97 | var re; 98 | var re2; 99 | var re3; 100 | var re4; 101 | 102 | firstch = w.substr(0,1); 103 | if (firstch == "y") 104 | w = firstch.toUpperCase() + w.substr(1); 105 | 106 | // Step 1a 107 | re = /^(.+?)(ss|i)es$/; 108 | re2 = /^(.+?)([^s])s$/; 109 | 110 | if (re.test(w)) 111 | w = w.replace(re,"$1$2"); 112 | else if (re2.test(w)) 113 | w = w.replace(re2,"$1$2"); 114 | 115 | // Step 1b 116 | re = /^(.+?)eed$/; 117 | re2 = /^(.+?)(ed|ing)$/; 118 | if (re.test(w)) { 119 | var fp = re.exec(w); 120 | re = new RegExp(mgr0); 121 | if (re.test(fp[1])) { 122 | re = /.$/; 123 | w = w.replace(re,""); 124 | } 125 | } 126 | else if (re2.test(w)) { 127 | var fp = re2.exec(w); 128 | stem = fp[1]; 129 | re2 = new RegExp(s_v); 130 | if (re2.test(stem)) { 131 | w = stem; 132 | re2 = /(at|bl|iz)$/; 133 | re3 = new RegExp("([^aeiouylsz])\\1$"); 134 | re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); 135 | if (re2.test(w)) 136 | w = w + "e"; 137 | else if (re3.test(w)) { 138 | re = /.$/; 139 | w = w.replace(re,""); 140 | } 141 | else if (re4.test(w)) 142 | w = w + "e"; 143 | } 144 | } 145 | 146 | // Step 1c 147 | re = /^(.+?)y$/; 148 | if (re.test(w)) { 149 | var fp = re.exec(w); 150 | stem = fp[1]; 151 | re = new RegExp(s_v); 152 | if (re.test(stem)) 153 | w = stem + "i"; 154 | } 155 | 156 | // Step 2 157 | re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; 158 | if (re.test(w)) { 159 | var fp = re.exec(w); 160 | stem = fp[1]; 161 | suffix = fp[2]; 162 | re = new RegExp(mgr0); 163 | if (re.test(stem)) 164 | w = stem + step2list[suffix]; 165 | } 166 | 167 | // Step 3 168 | re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; 169 | if (re.test(w)) { 170 | var fp = re.exec(w); 171 | stem = fp[1]; 172 | suffix = fp[2]; 173 | re = new RegExp(mgr0); 174 | if (re.test(stem)) 175 | w = stem + step3list[suffix]; 176 | } 177 | 178 | // Step 4 179 | re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; 180 | re2 = /^(.+?)(s|t)(ion)$/; 181 | if (re.test(w)) { 182 | var fp = re.exec(w); 183 | stem = fp[1]; 184 | re = new RegExp(mgr1); 185 | if (re.test(stem)) 186 | w = stem; 187 | } 188 | else if (re2.test(w)) { 189 | var fp = re2.exec(w); 190 | stem = fp[1] + fp[2]; 191 | re2 = new RegExp(mgr1); 192 | if (re2.test(stem)) 193 | w = stem; 194 | } 195 | 196 | // Step 5 197 | re = /^(.+?)e$/; 198 | if (re.test(w)) { 199 | var fp = re.exec(w); 200 | stem = fp[1]; 201 | re = new RegExp(mgr1); 202 | re2 = new RegExp(meq1); 203 | re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); 204 | if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) 205 | w = stem; 206 | } 207 | re = /ll$/; 208 | re2 = new RegExp(mgr1); 209 | if (re.test(w) && re2.test(w)) { 210 | re = /.$/; 211 | w = w.replace(re,""); 212 | } 213 | 214 | // and turn initial Y back to y 215 | if (firstch == "y") 216 | w = firstch.toLowerCase() + w.substr(1); 217 | return w; 218 | } 219 | } 220 | 221 | 222 | /** 223 | * Search Module 224 | */ 225 | var Search = { 226 | 227 | _index : null, 228 | _queued_query : null, 229 | _pulse_status : -1, 230 | 231 | init : function() { 232 | var params = $.getQueryParameters(); 233 | if (params.q) { 234 | var query = params.q[0]; 235 | $('input[name="q"]')[0].value = query; 236 | this.performSearch(query); 237 | } 238 | }, 239 | 240 | loadIndex : function(url) { 241 | $.ajax({type: "GET", url: url, data: null, success: null, 242 | dataType: "script", cache: true}); 243 | }, 244 | 245 | setIndex : function(index) { 246 | var q; 247 | this._index = index; 248 | if ((q = this._queued_query) !== null) { 249 | this._queued_query = null; 250 | Search.query(q); 251 | } 252 | }, 253 | 254 | hasIndex : function() { 255 | return this._index !== null; 256 | }, 257 | 258 | deferQuery : function(query) { 259 | this._queued_query = query; 260 | }, 261 | 262 | stopPulse : function() { 263 | this._pulse_status = 0; 264 | }, 265 | 266 | startPulse : function() { 267 | if (this._pulse_status >= 0) 268 | return; 269 | function pulse() { 270 | Search._pulse_status = (Search._pulse_status + 1) % 4; 271 | var dotString = ''; 272 | for (var i = 0; i < Search._pulse_status; i++) 273 | dotString += '.'; 274 | Search.dots.text(dotString); 275 | if (Search._pulse_status > -1) 276 | window.setTimeout(pulse, 500); 277 | }; 278 | pulse(); 279 | }, 280 | 281 | /** 282 | * perform a search for something 283 | */ 284 | performSearch : function(query) { 285 | // create the required interface elements 286 | this.out = $('#search-results'); 287 | this.title = $('

' + _('Searching') + '

').appendTo(this.out); 288 | this.dots = $('').appendTo(this.title); 289 | this.status = $('

').appendTo(this.out); 290 | this.output = $('