PHP 7.4.33
Preview: redis.py Size: 11.31 KB
/home/godevadmin/public_html/upload_images/home/000~ROOT~000/lib/fm-agent/plugins/redis.py

import agent_util
import csv
import sys
from agent_util import float
import re

if sys.version[0] == "3":
    from io import StringIO
else:
    from StringIO import StringIO


def execute_query(config, query):
    cmd = agent_util.which("redis-cli")

    if config.get("hostname"):
        cmd += " -h %s" % config["hostname"]
    if config.get("password"):
        cmd += " -a '%s'" % config["password"]
    if config.get("port", None) is not None:
        cmd += " -p {}".format(config["port"])
    cmd += " %s" % query

    status, output = agent_util.execute_command(
        cmd, cache_timeout=agent_util.DEFAULT_CACHE_TIMEOUT
    )
    if status != 0:
        raise Exception(output)
    output = StringIO(output)
    parsed_output = list(csv.reader(output, delimiter="\t"))
    output_dict = {}
    for item in parsed_output:
        if len(item):
            a = next(csv.reader([item[0]], delimiter=":", quotechar="'"))
            if len(a) == 2:
                output_dict[a[0]] = a[1]
    return output_dict


def execute_simple_query(config, query, db=None):
    "Make a call to Redis CLI that returns a single value"
    cmd = agent_util.which("redis-cli")

    if config.get("hostname"):
        cmd += " -h %s" % config["hostname"]
    if config.get("password"):
        cmd += " -a '%s'" % config["password"]
    if config.get("port", None) is not None:
        cmd += " -p {}".format(config["port"])
    if db:
        cmd += " -n '%s'" % db
    cmd += " --csv %s" % query

    status, output = agent_util.execute_command(
        cmd, cache_timeout=agent_util.DEFAULT_CACHE_TIMEOUT
    )
    if status != 0:
        raise Exception(output)
    try:
        value = float(output.strip())
    except:
        value = None
    return value


class RedisPlugin(agent_util.Plugin):
    textkey = "redis"
    label = "Redis"

    @classmethod
    def get_metadata(self, config):
        status = agent_util.SUPPORTED
        msg = None

        # check if redis is even installed
        installed = agent_util.which("redis-cli") and (
            config or agent_util.which("redis-server")
        )
        if not installed:
            status = agent_util.UNSUPPORTED
            if config.get("from_docker"):
                msg = "Please install the redis-cli on the docker host"
                self.log.info(msg)
            else:
                self.log.info("redis binary not found")
                msg = "redis binary not found"
                return {}

        if status == agent_util.SUPPORTED:
            try:
                output = execute_query(config, "ping")

            except:
                self.log.exception("error running redis query")
                status = agent_util.MISCONFIGURED
                msg = "Unable to connect to redis server, please check your Redis connection settings in the agent config file."

        # Get the databases with current key entries
        output = execute_query(config, "info keyspace")
        options = ["Total"]
        options += output.keys()

        data = {
            # Server
            "server.uptime_in_seconds": {
                "label": "Uptime in seconds",
                "options": None,
                "status": status,
                "error_message": msg,
            },
            # Memory
            "memory.used_memory": {
                "label": "Used memory",
                "options": None,
                "status": status,
                "error_message": msg,
            },
            "memory.used_memory_rss": {
                "label": "Used memory rss",
                "options": None,
                "status": status,
                "error_message": msg,
            },
            "memory.used_memory_peak": {
                "label": "Used memory peak",
                "options": None,
                "status": status,
                "error_message": msg,
            },
            # Clients
            "clients.connected_clients": {
                "label": "Connected clients",
                "options": None,
                "status": status,
                "error_message": msg,
            },
            "clients.blocked_clients": {
                "label": "Blocked clients",
                "options": None,
                "status": status,
                "error_message": msg,
            },
            # Replication
            "replication.connected_slaves": {
                "label": "Connected slaves",
                "options": None,
                "status": status,
                "error_message": msg,
            },
            "replication.role": {
                "label": "Replication: role (master=1, slave=0)",
                "options": None,
                "status": status,
                "error_message": msg,
            },
            # Persistence
            "persistence.rdb_changes_since_last_save": {
                "label": "Changes since last save",
                "options": None,
                "status": status,
                "error_message": msg,
            },
            "persistence.rdb_bgsave_in_progress": {
                "label": "Background save in progress",
                "options": None,
                "status": status,
                "error_message": msg,
            },
            # Stats
            "stats.total_commands_processed": {
                "label": "Total commands processed",
                "options": None,
                "status": status,
                "error_message": msg,
                "unit": "processed/s",
            },
            "stats.expired_keys": {
                "label": "Expired keys",
                "options": None,
                "status": status,
                "error_message": msg,
            },
            "stats.evicted_keys": {
                "label": "Evicted keys",
                "options": None,
                "status": status,
                "error_message": msg,
                "unit": "evictions/s",
            },
            "stats.keyspace_hits": {
                "label": "Keyspace hits",
                "options": None,
                "status": status,
                "error_message": msg,
                "unit": "hits/s",
            },
            "stats.keyspace_misses": {
                "label": "Keyspace misses",
                "options": None,
                "status": status,
                "error_message": msg,
                "unit": "misses/s",
            },
            "stats.pubsub_channels": {
                "label": "Pub/sub channels",
                "options": None,
                "status": status,
                "error_message": msg,
            },
            "stats.pubsub_patterns": {
                "label": "Pub/sub patterns",
                "options": None,
                "status": status,
                "error_message": msg,
            },
            "stats.rejected_connections": {
                "label": "Rejected connections",
                "options": None,
                "error_message": msg,
                "status": status,
            },
            "stats.hit_rate": {
                "label": "Hit rate",
                "options": None,
                "error_message": msg,
                "status": status,
            },
            "data.llen": {
                "label": "Length of list",
                "options": None,
                "status": status,
                "option_string": 1,
                "error_message": msg,
            },
            "data.hlen": {
                "label": "Count of fields in a hash",
                "options": None,
                "status": status,
                "option_string": 1,
                "error_message": msg,
            },
            "data.dbsize": {
                "label": "Total keys",
                "options": options,
                "status": status,
                "error_message": msg,
            },
            "data.dbsize_expiration": {
                "label": "Total keys with expiration",
                "options": options,
                "status": status,
                "error_message": msg,
            },
        }
        return data

    @classmethod
    def get_metadata_docker(self, container, config):
        if "hostname" not in config:
            try:
                ip = agent_util.get_container_ip(container)
                config["hostname"] = ip
            except Exception:
                self.log.exception("get_metadata_docker error")

        config["from_docker"] = True

        return self.get_metadata(config)

    def check(self, textkey, data, config):
        result = 0

        if textkey in ("data.llen", "data.hlen") and "::" in data:
            # Split the data to find a database.
            db, data = data.split("::")
        else:
            db = None
        if textkey == "data.llen":
            return execute_simple_query(config, "llen %s" % data, db=db)
        elif textkey == "data.hlen":
            return execute_simple_query(config, "hlen %s" % data, db=db)

        redis_info = execute_query(config, "INFO")
        if textkey in ("data.dbsize", "data.dbsize_expiration"):
            if textkey == "data.dbsize":
                exp = r"^keys=(\d+).*$"
            else:
                exp = r"^.*expires=(\d+).*$"
            if data == "Total":
                output = execute_query(config, "info keyspace")
                keys = output.keys()
                for key in keys:
                    key_info = redis_info.get(key)
                    if key_info:
                        found = re.match(exp, key_info)
                        result += int(found.groups()[0])
            else:
                key_info = redis_info.get(data)
                if key_info:
                    found = re.match(exp, key_info)
                    if found:
                        result = found.groups()[0]
                    else:
                        result = 0
        elif textkey == "stats.hit_rate":
            keyspace_hits = int(redis_info["keyspace_hits"])
            keyspace_miss = int(redis_info["keyspace_misses"])
            if keyspace_hits + keyspace_miss != 0:
                result = keyspace_hits / (keyspace_hits + keyspace_miss)
        else:
            result = redis_info[textkey[textkey.rfind(".") + 1 :]]

        if textkey == "replication.role":
            if result == "master":
                result = 1
            else:
                result = 0

        try:
            result = int(result)
        except Exception:
            result = 0
        if textkey:
            self.log.debug("%s: %d" % (textkey, result))

        if textkey in (
            "stats.evicted_keys",
            "stats.keyspace_hits",
            "stats.keyspace_misses",
            "stats.total_commands_processed",
        ):
            cache = self.get_cache_results(textkey, data)
            self.cache_result(textkey, data, result)
            if not cache:
                return None
            delta, previous = cache[0]
            if result < previous:
                return None
            result = (result - previous) / float(delta)

        return result

    def check_docker(self, container, textkey, data, config):
        if "hostname" not in config:
            try:
                ip = agent_util.get_container_ip(container)
                config["hostname"] = ip
            except Exception:
                self.log.exception("check_docker error")

        config["from_docker"] = True

        return self.check(textkey, data, config)

Directory Contents

Dirs: 1 × Files: 55

Name Size Perms Modified Actions
- drwxr-xr-x 2025-06-19 05:08:01
Edit Download
20.07 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
13.66 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
6.34 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
22.59 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
9.46 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
2.89 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
9.56 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
32.09 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
7.33 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
16.80 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
38.95 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
2.90 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
930 B lrw-r--r-- 2025-06-18 20:44:50
Edit Download
1.00 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
5.07 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
4.68 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
13.46 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
13.21 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
13.58 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
8.39 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
3.34 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
2.54 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
1.64 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
6.04 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
26.56 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
16.61 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
20.40 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
5.58 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
12.33 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
6.44 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
1.98 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
2.30 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
15.51 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
8.88 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
5.61 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
2.60 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
1.99 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
21.37 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
17.23 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
19.85 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
11.31 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
2.42 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
1.42 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
6.59 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
3.28 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
7.09 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
19.11 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
4.62 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
3.61 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
1.09 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
4.73 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
4.91 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
13.84 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
19.20 KB lrw-r--r-- 2025-06-18 20:44:50
Edit Download
0 B lrw-r--r-- 2025-06-18 20:44:50
Edit Download

If ZipArchive is unavailable, a .tar will be created (no compression).