Skip to content

Feature request to add a prometheus collector in jedis #3069

Open
@aarengee

Description

@aarengee

Feature request to add a prometheus collector in jedis

Add a implementation of Collector in src/main/java/redis/clients/jedis/metrics package or utils maybe

Basically a 1:1 clone of what HikariCP ships with here

Using this all

  • Jedispool instances behind a JedisCluster object created for a redis cluster ( 6 pools for 6 node cluster )
  • Jedispool instances for a standalone redis master instance ( 1 pool for a single redis instance )

can be instrumented using a simple line of code RedisCollector.getCollector().track(myjedisClusterOrPool)

Why as part of jedis and not as left upto user in there code.

  • In my opinion shipping it with jedis will add value to the library as it provides visibility to the user about the metrics as an inbuilt rather than having to instrument it separately.

  • As and when we add more metrics we can keep adding gauges/histogram/counter to the same collector . And the user wont even know these metrics are automatically available in the same registry . As soon as you upgrade your jedis library dependency metric is available. If I create it as a separate project then a pull request needs to be raised on that project , that project will have to upgrade jedis version , add those new metrics . All that

  • Prometheus is one of the most common timeseries in the industry with a simple to implement interface .

Why not do this in jedis ?

  • Need to add io.prometheus as a dependency
  • jedis wants to be light weight and not be opinionated about any other tool like prometheus

Sample code

import io.prometheus.client.Collector;
import io.prometheus.client.GaugeMetricFamily;
import io.prometheus.client.CollectorRegistry;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPool;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;

import static java.util.Collections.singletonList;

public class RedisCollector extends Collector {

  private static final List<String> LABEL_NAMES = singletonList("host");

  private static Map<String, JedisPool> poolStatsMap = new ConcurrentHashMap<>();

  private static RedisCollector redisCollector;

  public static RedisCollector getCollector() {
    if (redisCollector == null) {
      redisCollector = new RedisCollector().register();
    }
    return redisCollector;
  }

  public static RedisCollector getCollector(CollectorRegistry registry) {
    if (redisCollector == null) {
      redisCollector = new RedisCollector();
      registry.register(redisCollector);
    }
    return redisCollector;
  }

  @Override
  public List<MetricFamilySamples> collect() {
    return Arrays.asList(
        createGauge("jedis_pool_num_active", "Jedis Pool Active connections", JedisPool::getNumActive),
        createGauge("jedis_pool_idle_connections", "Jedis Pool Idle connections", JedisPool::getNumIdle),
        createGauge("jedis_pool_num_waiters", "Jedis Pool Waiting connections", JedisPool::getNumWaiters)

    );
  }

  public void track(JedisCluster cluster) {
    poolStatsMap = cluster.getClusterNodes();
  }

  public void track(String poolName, JedisPool pool) {
    poolStatsMap.put(poolName, pool);
  

  private GaugeMetricFamily createGauge(String metric, String help,
                                        Function<JedisPool, Integer> driverFunction) {
    GaugeMetricFamily metricFamily = new GaugeMetricFamily(metric, help, LABEL_NAMES);
    poolStatsMap.forEach((poolName, pool) -> metricFamily.addMetric(singletonList(poolName), driverFunction.apply(pool)));
    return metricFamily;
  }
}

Sample metrics

jedis_cluster_num_active{host="127.0.0.1:7006",} 0.0
jedis_cluster_num_active{host="127.0.0.1:7004",} 0.0
jedis_cluster_num_active{host="127.0.0.1:7005",} 0.0
jedis_cluster_num_active{host="127.0.0.1:7002",} 0.0
jedis_cluster_num_active{host="127.0.0.1:7003",} 0.0
jedis_cluster_num_active{host="127.0.0.1:7001",} 1.0

jedis_cluster_idle_connections{host="127.0.0.1:7006",} 50.0
jedis_cluster_idle_connections{host="127.0.0.1:7004",} 50.0
jedis_cluster_idle_connections{host="127.0.0.1:7005",} 50.0
jedis_cluster_idle_connections{host="127.0.0.1:7002",} 50.0
jedis_cluster_idle_connections{host="127.0.0.1:7003",} 50.0
jedis_cluster_idle_connections{host="127.0.0.1:7001",} 50.0

jedis_cluster_num_waiters{host="127.0.0.1:7006",} 0.0
jedis_cluster_num_waiters{host="127.0.0.1:7004",} 0.0
jedis_cluster_num_waiters{host="127.0.0.1:7005",} 0.0
jedis_cluster_num_waiters{host="127.0.0.1:7002",} 0.0
jedis_cluster_num_waiters{host="127.0.0.1:7003",} 0.0
jedis_cluster_num_waiters{host="127.0.0.1:7001",} 0.0

I would really like to contribute.
Thanks for your consideration .

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions