(self, conn, tags)
Compute the length of the configured keys across all the databases
Compute the length of the configured keys across all the databases
Compute the length of the configured keys across all the databases
def _check_key_lengths(self, conn, tags):
        """
        Compute the length of the configured keys across all the databases
        """
        key_list = self.instance.get('keys')

        if key_list is None:
            return

        instance_db = self.instance.get('db')

        if not isinstance(key_list, list) or not key_list:
            self.warning("keys in redis configuration is either not a list or empty")
            return

        warn_on_missing_keys = is_affirmative(self.instance.get("warn_on_missing_keys", True))

        # get all the available databases
        databases = list(conn.info('keyspace'))
        if not databases:
            self.warning("Redis database is empty")
            for key in key_list:
                key_tags = ['key:{}'.format(key)]
                if instance_db:
                    key_tags.append('redis_db:db{}'.format(instance_db))
                key_tags.extend(tags)
                self.gauge('redis.key.length', 0, tags=key_tags)
                if warn_on_missing_keys:
                    self.warning("%s key not found in redis", key)
            return

        # convert to integer the output of `keyspace`, from `db0` to `0`
        # and store items in a set
        databases = [int(dbstring[2:]) for dbstring in databases]

        # user might have configured the instance to target one specific db
        if instance_db:
            if instance_db not in databases:
                self.warning("Cannot find database %s", instance_db)
                return
            databases = [instance_db]

        # maps a key to the total length across databases
        lengths_overall = defaultdict(int)

        # don't overwrite the configured instance, use a copy
        tmp_instance = deepcopy(self.instance)

        for db in databases:
            lengths = defaultdict(lambda: defaultdict(int))
            tmp_instance['db'] = db
            db_conn = self._get_conn(tmp_instance)

            for key_pattern in key_list:
                if re.search(r"(?<!\\)[*?[]", key_pattern):
                    keys = db_conn.scan_iter(match=key_pattern)
                else:
                    keys = [key_pattern]

                for key in keys:
                    text_key = ensure_unicode(key)
                    try:
                        key_type = ensure_unicode(db_conn.type(key))
                    except redis.ResponseError:
                        self.log.info("key %s on remote server; skipping", text_key)
                        continue

                    if key_type == 'list':
                        keylen = db_conn.llen(key)
                        lengths[text_key]["length"] += keylen
                        lengths_overall[text_key] += keylen
                    elif key_type == 'set':
                        keylen = db_conn.scard(key)
                        lengths[text_key]["length"] += keylen
                        lengths_overall[text_key] += keylen
                    elif key_type == 'zset':
                        keylen = db_conn.zcard(key)
                        lengths[text_key]["length"] += keylen
                        lengths_overall[text_key] += keylen
                    elif key_type == 'hash':
                        keylen = db_conn.hlen(key)
                        lengths[text_key]["length"] += keylen
                        lengths_overall[text_key] += keylen
                    elif key_type == 'string':
                        # Send 1 if the key exists as a string
                        lengths[text_key]["length"] += 1
                        lengths_overall[text_key] += 1
                    elif key_type == 'stream':
                        keylen = db_conn.xlen(key)
                        lengths[text_key]["length"] += 1
                        lengths_overall[text_key] += 1
                    else:
                        # If the type is unknown, it might be because the key doesn't exist,
                        # which can be because the list is empty. So always send 0 in that case.
                        lengths[text_key]["length"] += 0
                        lengths_overall[text_key] += 0

                    # Tagging with key_type since the same key can exist with a
                    # different key_type in another db
                    lengths[text_key]["key_type"] = key_type

            # Send the metrics for each db in the redis instance.
            for key, total in iteritems(lengths):
                # Only send non-zeros if tagged per db.
                if total["length"] > 0:
                    self.gauge(
                        'redis.key.length',
                        total["length"],
                        tags=tags
                        + ['key:{}'.format(key), 'key_type:{}'.format(total["key_type"]), 'redis_db:db{}'.format(db)],
                    )

        # Warn if a key is missing from the entire redis instance.
        # Send 0 if the key is missing/empty from the entire redis instance.
        for key, total in iteritems(lengths_overall):
            if total == 0:
                key_tags = ['key:{}'.format(key)]
                if instance_db:
                    key_tags.append('redis_db:db{}'.format(instance_db))
                key_tags.extend(tags)
                self.gauge('redis.key.length', 0, tags=key_tags)
                if warn_on_missing_keys:
                    self.warning("%s key not found in redis", key)
def _check_key_lengths ( self , conn , tags ) : key_list = self . instance . get ( 'keys' ) if key_list is None : return instance_db = self . instance . get ( 'db' ) if not isinstance ( key_list , list ) or not key_list : self . warning ( "keys in redis configuration is either not a list or empty" ) return warn_on_missing_keys = is_affirmative ( self . instance . get ( "warn_on_missing_keys" , True ) ) # get all the available databases databases = list ( conn . info ( 'keyspace' ) ) if not databases : self . warning ( "Redis database is empty" ) for key in key_list : key_tags = [ 'key:{}' . format ( key ) ] if instance_db : key_tags . append ( 'redis_db:db{}' . format ( instance_db ) ) key_tags . extend ( tags ) self . gauge ( 'redis.key.length' , 0 , tags = key_tags ) if warn_on_missing_keys : self . warning ( "%s key not found in redis" , key ) return # convert to integer the output of `keyspace`, from `db0` to `0` # and store items in a set databases = [ int ( dbstring [ 2 : ] ) for dbstring in databases ] # user might have configured the instance to target one specific db if instance_db : if instance_db not in databases : self . warning ( "Cannot find database %s" , instance_db ) return databases = [ instance_db ] # maps a key to the total length across databases lengths_overall = defaultdict ( int ) # don't overwrite the configured instance, use a copy tmp_instance = deepcopy ( self . instance ) for db in databases : lengths = defaultdict ( lambda : defaultdict ( int ) ) tmp_instance [ 'db' ] = db db_conn = self . _get_conn ( tmp_instance ) for key_pattern in key_list : if re . search ( r"(?<!\\)[*?[]" , key_pattern ) : keys = db_conn . scan_iter ( match = key_pattern ) else : keys = [ key_pattern ] for key in keys : text_key = ensure_unicode ( key ) try : key_type = ensure_unicode ( db_conn . type ( key ) ) except redis . ResponseError : self . log . info ( "key %s on remote server; skipping" , text_key ) continue if key_type == 'list' : keylen = db_conn . llen ( key ) lengths [ text_key ] [ "length" ] += keylen lengths_overall [ text_key ] += keylen elif key_type == 'set' : keylen = db_conn . scard ( key ) lengths [ text_key ] [ "length" ] += keylen lengths_overall [ text_key ] += keylen elif key_type == 'zset' : keylen = db_conn . zcard ( key ) lengths [ text_key ] [ "length" ] += keylen lengths_overall [ text_key ] += keylen elif key_type == 'hash' : keylen = db_conn . hlen ( key ) lengths [ text_key ] [ "length" ] += keylen lengths_overall [ text_key ] += keylen elif key_type == 'string' : # Send 1 if the key exists as a string lengths [ text_key ] [ "length" ] += 1 lengths_overall [ text_key ] += 1 elif key_type == 'stream' : keylen = db_conn . xlen ( key ) lengths [ text_key ] [ "length" ] += 1 lengths_overall [ text_key ] += 1 else : # If the type is unknown, it might be because the key doesn't exist, # which can be because the list is empty. So always send 0 in that case. lengths [ text_key ] [ "length" ] += 0 lengths_overall [ text_key ] += 0 # Tagging with key_type since the same key can exist with a # different key_type in another db lengths [ text_key ] [ "key_type" ] = key_type # Send the metrics for each db in the redis instance. for key , total in iteritems ( lengths ) : # Only send non-zeros if tagged per db. if total [ "length" ] > 0 : self . gauge ( 'redis.key.length' , total [ "length" ] , tags = tags + [ 'key:{}' . format ( key ) , 'key_type:{}' . format ( total [ "key_type" ] ) , 'redis_db:db{}' . format ( db ) ] , ) # Warn if a key is missing from the entire redis instance. # Send 0 if the key is missing/empty from the entire redis instance. for key , total in iteritems ( lengths_overall ) : if total == 0 : key_tags = [ 'key:{}' . format ( key ) ] if instance_db : key_tags . append ( 'redis_db:db{}' . format ( instance_db ) ) key_tags . extend ( tags ) self . gauge ( 'redis.key.length' , 0 , tags = key_tags ) if warn_on_missing_keys : self . warning ( "%s key not found in redis" , key )