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:
parent
137a0f5cf9
commit
a30fe1d79d
|
@ -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"
|
||||
}
|
|
@ -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
|
||||
diskcache
|
||||
openstacksdk>=0.9.14
|
||||
pymemcache>=1.2.9,!=1.3.0 # Apache 2.0 License
|
||||
psutil>=5.2.0
|
||||
six
|
||||
stevedore
|
||||
|
|
|
@ -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'
|
Loading…
Reference in New Issue