Add memcache plugin
This patch adds a memcache plugin along with tests and documentation. Implements: blueprint monitorstack Change-Id: Iefb0c0912078713c26387e02e135d70d7a96a7dc
This commit is contained in:
105
doc/source/plugins-base/plugin-memcache.rst
Normal file
105
doc/source/plugins-base/plugin-memcache.rst
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
``memcache`` - get statistics from a memcache server
|
||||||
|
====================================================
|
||||||
|
|
||||||
|
The memcache plugin connects to a memcache server to retrieve statistics.
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-----
|
||||||
|
|
||||||
|
The plugin has two optional arguments:
|
||||||
|
|
||||||
|
* ``host`` - the hostname or IP address of the memcache server
|
||||||
|
* ``port`` - the port number of the memcache server
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
Usage: monitorstack memcache [OPTIONS]
|
||||||
|
|
||||||
|
Get memcached stats.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--host TEXT memcached host to query
|
||||||
|
--port INTEGER memcached server port
|
||||||
|
--help Show this message and exit.
|
||||||
|
|
||||||
|
|
||||||
|
Example
|
||||||
|
-------
|
||||||
|
|
||||||
|
Run the plugin:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ monitorstack memcache
|
||||||
|
|
||||||
|
Example output in JSON format:
|
||||||
|
|
||||||
|
.. code-block:: json
|
||||||
|
|
||||||
|
{
|
||||||
|
"variables": {
|
||||||
|
"auth_cmds": 0,
|
||||||
|
"crawler_items_checked": 0,
|
||||||
|
"reclaimed": 0,
|
||||||
|
"get_expired": 0,
|
||||||
|
"curr_items": 0,
|
||||||
|
"pid": 24627,
|
||||||
|
"malloc_fails": 0,
|
||||||
|
"time_in_listen_disabled_us": 0,
|
||||||
|
"expired_unfetched": 0,
|
||||||
|
"hash_is_expanding": false,
|
||||||
|
"cas_hits": 0,
|
||||||
|
"uptime": 8,
|
||||||
|
"touch_hits": 0,
|
||||||
|
"delete_misses": 0,
|
||||||
|
"listen_disabled_num": 0,
|
||||||
|
"cas_misses": 0,
|
||||||
|
"decr_hits": 0,
|
||||||
|
"cmd_touch": 0,
|
||||||
|
"incr_hits": 0,
|
||||||
|
"version": "1.4.33",
|
||||||
|
"limit_maxbytes": 67108864,
|
||||||
|
"total_items": 0,
|
||||||
|
"bytes_written": 0,
|
||||||
|
"incr_misses": 0,
|
||||||
|
"accepting_conns": 1,
|
||||||
|
"rusage_system": 0.014981,
|
||||||
|
"log_watcher_sent": 0,
|
||||||
|
"get_flushed": 0,
|
||||||
|
"cmd_get": 0,
|
||||||
|
"curr_connections": 4,
|
||||||
|
"log_worker_written": 0,
|
||||||
|
"log_watcher_skipped": 0,
|
||||||
|
"touch_misses": 0,
|
||||||
|
"threads": 4,
|
||||||
|
"total_connections": 5,
|
||||||
|
"cmd_set": 0,
|
||||||
|
"libevent": "2.0.22-stable",
|
||||||
|
"conn_yields": 0,
|
||||||
|
"get_misses": 0,
|
||||||
|
"reserved_fds": 20,
|
||||||
|
"bytes_read": 8,
|
||||||
|
"hash_bytes": 524288,
|
||||||
|
"evicted_unfetched": 0,
|
||||||
|
"cas_badval": 0,
|
||||||
|
"cmd_flush": 0,
|
||||||
|
"lrutail_reflocked": 0,
|
||||||
|
"evictions": 0,
|
||||||
|
"bytes": 0,
|
||||||
|
"crawler_reclaimed": 0,
|
||||||
|
"connection_structures": 5,
|
||||||
|
"hash_power_level": 16,
|
||||||
|
"log_worker_dropped": 0,
|
||||||
|
"auth_errors": 0,
|
||||||
|
"rusage_user": 0.005598,
|
||||||
|
"time": 1493240773,
|
||||||
|
"delete_hits": 0,
|
||||||
|
"pointer_size": 64,
|
||||||
|
"decr_misses": 0,
|
||||||
|
"get_hits": 0
|
||||||
|
},
|
||||||
|
"message": "memcached is ok",
|
||||||
|
"meta": {},
|
||||||
|
"exit_code": 0,
|
||||||
|
"measurement_name": "memcache"
|
||||||
|
}
|
57
monitorstack/plugins/memcache.py
Normal file
57
monitorstack/plugins/memcache.py
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
# Copyright 2017, Major Hayden <major@mhtx.net>
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
"""Get memcached stats."""
|
||||||
|
import click
|
||||||
|
|
||||||
|
from monitorstack import utils
|
||||||
|
from monitorstack.cli import pass_context
|
||||||
|
|
||||||
|
from pymemcache.client.base import Client
|
||||||
|
|
||||||
|
DOC = """Get memcached stats."""
|
||||||
|
COMMAND_NAME = 'memcache'
|
||||||
|
|
||||||
|
|
||||||
|
@click.command(COMMAND_NAME, short_help=DOC)
|
||||||
|
@click.option('--host', help='memcached host to query', default='127.0.0.1')
|
||||||
|
@click.option('--port', help='memcached server port', default=11211)
|
||||||
|
@pass_context
|
||||||
|
def cli(ctx, host, port):
|
||||||
|
"""Get memcached stats."""
|
||||||
|
output = {
|
||||||
|
'exit_code': 0,
|
||||||
|
'message': 'memcached is ok',
|
||||||
|
'measurement_name': 'memcache',
|
||||||
|
'meta': {},
|
||||||
|
'variables': {}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Connect to memcache and retrieve our stats
|
||||||
|
try:
|
||||||
|
stats = get_memcached_stats(host, port)
|
||||||
|
output['variables'] = stats
|
||||||
|
except Exception as exp:
|
||||||
|
output['exit_code'] = 1
|
||||||
|
output['message'] = '{} failed -- {}'.format(
|
||||||
|
COMMAND_NAME,
|
||||||
|
utils.log_exception(exp=exp)
|
||||||
|
)
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
|
|
||||||
|
def get_memcached_stats(host, port):
|
||||||
|
"""Connect to memcache server for stats."""
|
||||||
|
conn = Client((host, port))
|
||||||
|
return conn.stats()
|
@@ -1,6 +1,7 @@
|
|||||||
click
|
click
|
||||||
diskcache
|
diskcache
|
||||||
openstacksdk>=0.9.14
|
openstacksdk>=0.9.14
|
||||||
|
pymemcache>=1.2.9,!=1.3.0 # Apache 2.0 License
|
||||||
psutil>=5.2.0
|
psutil>=5.2.0
|
||||||
six
|
six
|
||||||
stevedore
|
stevedore
|
||||||
|
78
tests/test_plugin_memcache.py
Normal file
78
tests/test_plugin_memcache.py
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
# Copyright 2017, Major Hayden <major@mhtx.net>
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
"""Tests for the memcache plugin."""
|
||||||
|
from monitorstack.plugins import memcache as monitorstack_memcache
|
||||||
|
|
||||||
|
import pymemcache
|
||||||
|
|
||||||
|
import tests
|
||||||
|
|
||||||
|
|
||||||
|
class TestMemcache(object):
|
||||||
|
"""Tests for the memcache plugin."""
|
||||||
|
|
||||||
|
def test_success(self, monkeypatch):
|
||||||
|
"""Ensure the run() method works."""
|
||||||
|
def mock_get_memcached_stats(host, port):
|
||||||
|
"""Mock the get_memcached_stats() method."""
|
||||||
|
return {'parameter': 'value'}
|
||||||
|
|
||||||
|
monkeypatch.setattr(
|
||||||
|
monitorstack_memcache,
|
||||||
|
'get_memcached_stats',
|
||||||
|
mock_get_memcached_stats
|
||||||
|
)
|
||||||
|
result = tests.runner('memcache')
|
||||||
|
assert result['variables']['parameter'] == 'value'
|
||||||
|
assert result['measurement_name'] == "memcache"
|
||||||
|
assert result['exit_code'] == 0
|
||||||
|
|
||||||
|
def test_failure(self, monkeypatch):
|
||||||
|
"""Ensure the run() method works."""
|
||||||
|
def mock_get_memcached_stats(host, port):
|
||||||
|
"""Mock the get_memcached_stats() method."""
|
||||||
|
raise Exception('Connection failed')
|
||||||
|
|
||||||
|
monkeypatch.setattr(
|
||||||
|
monitorstack_memcache,
|
||||||
|
'get_memcached_stats',
|
||||||
|
mock_get_memcached_stats
|
||||||
|
)
|
||||||
|
result = tests.runner('memcache')
|
||||||
|
assert 'Connection failed' in result['message']
|
||||||
|
assert result['measurement_name'] == "memcache"
|
||||||
|
assert result['exit_code'] == 1
|
||||||
|
|
||||||
|
def test_get_memcached_stats(self, monkeypatch):
|
||||||
|
"""Ensure that get_memcached_stats() works."""
|
||||||
|
def mock_memcache_client(cls, (conn_tuple)):
|
||||||
|
"""Mock a memcache client class."""
|
||||||
|
return None
|
||||||
|
|
||||||
|
def mock_memcache_stats(toot):
|
||||||
|
"""Mock a memcache client class."""
|
||||||
|
return {'parameter': 'value'}
|
||||||
|
|
||||||
|
monkeypatch.setattr(
|
||||||
|
pymemcache.client.base.Client,
|
||||||
|
'__init__',
|
||||||
|
mock_memcache_client
|
||||||
|
)
|
||||||
|
monkeypatch.setattr(
|
||||||
|
pymemcache.client.base.Client,
|
||||||
|
'stats',
|
||||||
|
mock_memcache_stats
|
||||||
|
)
|
||||||
|
result = monitorstack_memcache.get_memcached_stats('localhost', 11211)
|
||||||
|
assert result['parameter'] == 'value'
|
Reference in New Issue
Block a user