From e3b8ffbe45f03a2608f021f07fc9c2ba4acaacf7 Mon Sep 17 00:00:00 2001 From: carrot Date: Tue, 20 Feb 2024 03:03:30 +0300 Subject: [PATCH 1/3] add LATENCY LATEST, LATENCY HISTORY and LATENCY RESET commands --- .../redis/clients/jedis/BuilderFactory.java | 47 ++++++++++++++++ src/main/java/redis/clients/jedis/Jedis.java | 21 ++++++++ .../java/redis/clients/jedis/Protocol.java | 22 +++++++- .../jedis/commands/ServerCommands.java | 12 +++++ .../jedis/resps/LatencyHistoryInfo.java | 38 +++++++++++++ .../jedis/resps/LatencyLatestInfo.java | 53 +++++++++++++++++++ .../commands/jedis/ControlCommandsTest.java | 19 +++++++ 7 files changed, 211 insertions(+), 1 deletion(-) create mode 100644 src/main/java/redis/clients/jedis/resps/LatencyHistoryInfo.java create mode 100644 src/main/java/redis/clients/jedis/resps/LatencyLatestInfo.java diff --git a/src/main/java/redis/clients/jedis/BuilderFactory.java b/src/main/java/redis/clients/jedis/BuilderFactory.java index c7349f3e89..18bcc5a31c 100644 --- a/src/main/java/redis/clients/jedis/BuilderFactory.java +++ b/src/main/java/redis/clients/jedis/BuilderFactory.java @@ -997,6 +997,53 @@ public Map build(Object data) { } }; + public static final Builder> LATENCY_LATEST_RESPONSE = new Builder>() { + @Override + public Map build(Object data) { + if (data == null) { + return null; + } + + List rawList = (List) data; + Map map = new HashMap<>(rawList.size()); + + for (Object rawLatencyLatestInfo : rawList) { + if (rawLatencyLatestInfo == null) { + continue; + } + + LatencyLatestInfo latestInfo = LatencyLatestInfo.LATENCY_LATEST_BUILDER.build(rawLatencyLatestInfo); + String name = latestInfo.getCommand(); + map.put(name, latestInfo); + } + + return map; + } + }; + + public static final Builder> LATENCY_HISTORY_RESPONSE = new Builder>() { + @Override + public List build(Object data) { + if (data == null) { + return null; + } + + List rawList = (List) data; + List response = new ArrayList<>(rawList.size()); + + for (Object rawLatencyHistoryInfo : rawList) { + if (rawLatencyHistoryInfo == null) { + continue; + } + + LatencyHistoryInfo historyInfo = LatencyHistoryInfo.LATENCY_HISTORY_BUILDER.build(rawLatencyHistoryInfo); + response.add(historyInfo); + } + + return response; + } + }; + private static final Builder>> CLUSTER_SHARD_SLOTS_RANGES = new Builder>>() { @Override diff --git a/src/main/java/redis/clients/jedis/Jedis.java b/src/main/java/redis/clients/jedis/Jedis.java index 181fe279a2..f70a09d271 100644 --- a/src/main/java/redis/clients/jedis/Jedis.java +++ b/src/main/java/redis/clients/jedis/Jedis.java @@ -14,6 +14,7 @@ import java.util.Map.Entry; import java.util.Set; import java.util.stream.Collectors; +import java.util.Arrays; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLParameters; @@ -9280,6 +9281,26 @@ public String latencyDoctor() { return connection.getBulkReply(); } + public Map latencyLatest() { + checkIsInMultiOrPipeline(); + connection.sendCommand(LATENCY, LATEST); + return BuilderFactory.LATENCY_LATEST_RESPONSE.build(connection.getOne()); + } + + public List latencyHistory(EventKeyword event) { + checkIsInMultiOrPipeline(); + connection.sendCommand(new CommandArguments(LATENCY).add(HISTORY).add(event)); + return BuilderFactory.LATENCY_HISTORY_RESPONSE.build(connection.getOne()); + } + + public long latencyReset(EventKeyword... events) { + checkIsInMultiOrPipeline(); + CommandArguments arguments = new CommandArguments(LATENCY).add(Keyword.RESET); + Arrays.stream(events).forEach(arguments::add); + connection.sendCommand(arguments); + return connection.getIntegerReply(); + } + @Override public StreamEntryID xadd(final String key, final StreamEntryID id, final Map hash) { checkIsInMultiOrPipeline(); diff --git a/src/main/java/redis/clients/jedis/Protocol.java b/src/main/java/redis/clients/jedis/Protocol.java index cba60115b3..8109760fa8 100644 --- a/src/main/java/redis/clients/jedis/Protocol.java +++ b/src/main/java/redis/clients/jedis/Protocol.java @@ -299,7 +299,7 @@ public static enum Keyword implements Rawable { REV, WITHCOORD, WITHDIST, WITHHASH, ANY, FROMMEMBER, FROMLONLAT, BYRADIUS, BYBOX, BYLEX, BYSCORE, STOREDIST, TO, FORCE, TIMEOUT, DB, UNLOAD, ABORT, IDX, MINMATCHLEN, WITHMATCHLEN, FULL, DELETE, LIBRARYNAME, WITHCODE, DESCRIPTION, GETKEYS, GETKEYSANDFLAGS, DOCS, FILTERBY, DUMP, - MODULE, ACLCAT, PATTERN, DOCTOR, USAGE, SAMPLES, PURGE, STATS, LOADEX, CONFIG, ARGS, RANK, + MODULE, ACLCAT, PATTERN, DOCTOR, LATEST, HISTORY, USAGE, SAMPLES, PURGE, STATS, LOADEX, CONFIG, ARGS, RANK, NOW, VERSION, ADDR, SKIPME, USER, LADDR, CHANNELS, NUMPAT, NUMSUB, SHARDCHANNELS, SHARDNUMSUB; @@ -371,4 +371,24 @@ public byte[] getRaw() { return raw; } } + + public static enum EventKeyword implements Rawable { + ACTIVE_DEFRAG_CYCLE("active-defrag-cycle"), AOF_FSYNC_ALWAYS("aof-fsync-always"), AOF_STAT("aof-stat"), + AOF_REWRITE_DIFF_WRITE("aof-rewrite-diff-write"), AOF_RENAME("aof-rename"), AOF_WRITE("aof-write"), + AOF_WRITE_ACTIVE_CHILD("aof-write-active-child"), AOF_WRITE_ALONE("aof-write-alone"), + AOF_WRITE_PENDING_FSYNC("aof-write-pending-fsync"), COMMAND("command"), EXPIRE_CYCLE("expire-cycle"), + EVICTION_CYCLE("eviction-cycle"), EVICTION_DEL("eviction-del"), FAST_COMMAND("fast-command"), + FORK("fork"), RDB_UNLINK_TEMP_FILE("rdb-unlink-temp-file"); + + private final byte[] raw; + + EventKeyword(String s) { + raw = SafeEncoder.encode(s); + } + + @Override + public byte[] getRaw() { + return raw; + } + } } diff --git a/src/main/java/redis/clients/jedis/commands/ServerCommands.java b/src/main/java/redis/clients/jedis/commands/ServerCommands.java index 511357ac1d..9115ea433f 100644 --- a/src/main/java/redis/clients/jedis/commands/ServerCommands.java +++ b/src/main/java/redis/clients/jedis/commands/ServerCommands.java @@ -1,12 +1,18 @@ package redis.clients.jedis.commands; +import redis.clients.jedis.Protocol; import redis.clients.jedis.args.FlushMode; import redis.clients.jedis.args.SaveMode; import redis.clients.jedis.exceptions.JedisException; import redis.clients.jedis.params.LolwutParams; import redis.clients.jedis.params.ShutdownParams; +import redis.clients.jedis.resps.LatencyHistoryInfo; +import redis.clients.jedis.resps.LatencyLatestInfo; import redis.clients.jedis.util.KeyValue; +import java.util.List; +import java.util.Map; + public interface ServerCommands { /** @@ -246,4 +252,10 @@ default void shutdown(SaveMode saveMode) throws JedisException { * @return the report */ String latencyDoctor(); + + Map latencyLatest(); + + List latencyHistory(Protocol.EventKeyword events); + + long latencyReset(Protocol.EventKeyword... events); } diff --git a/src/main/java/redis/clients/jedis/resps/LatencyHistoryInfo.java b/src/main/java/redis/clients/jedis/resps/LatencyHistoryInfo.java new file mode 100644 index 0000000000..68867e74e6 --- /dev/null +++ b/src/main/java/redis/clients/jedis/resps/LatencyHistoryInfo.java @@ -0,0 +1,38 @@ +package redis.clients.jedis.resps; + +import redis.clients.jedis.Builder; + +import java.util.List; + +import static redis.clients.jedis.BuilderFactory.LONG; + +public class LatencyHistoryInfo { + + private final long timestamp; + private final long latency; + + public LatencyHistoryInfo(long timestamp, long latency) { + this.timestamp = timestamp; + this.latency = latency; + } + + public long getTimestamp() { + return timestamp; + } + + public long getLatency() { + return latency; + } + + public static final Builder LATENCY_HISTORY_BUILDER = new Builder() { + @Override + public LatencyHistoryInfo build(Object data) { + List commandData = (List) data; + + long timestamp = LONG.build(commandData.get(0)); + long latency = LONG.build(commandData.get(1)); + + return new LatencyHistoryInfo(timestamp, latency); + } + }; +} diff --git a/src/main/java/redis/clients/jedis/resps/LatencyLatestInfo.java b/src/main/java/redis/clients/jedis/resps/LatencyLatestInfo.java new file mode 100644 index 0000000000..b441ea9d75 --- /dev/null +++ b/src/main/java/redis/clients/jedis/resps/LatencyLatestInfo.java @@ -0,0 +1,53 @@ +package redis.clients.jedis.resps; + +import redis.clients.jedis.Builder; + +import java.util.List; + +import static redis.clients.jedis.BuilderFactory.LONG; +import static redis.clients.jedis.BuilderFactory.STRING; + +public class LatencyLatestInfo { + + private final String command; + private final long timestamp; + private final long lastEventLatency; + private final long maxEventLatency; + + public LatencyLatestInfo(String command, long timestamp, long lastEventLatency, long maxEventLatency) { + this.command = command; + this.timestamp = timestamp; + this.lastEventLatency = lastEventLatency; + this.maxEventLatency = maxEventLatency; + } + + public String getCommand() { + return command; + } + + public long getTimestamp() { + return timestamp; + } + + public long getLastEventLatency() { + return lastEventLatency; + } + + public long getMaxEventLatency() { + return maxEventLatency; + } + + public static final Builder LATENCY_LATEST_BUILDER = new Builder() { + @Override + public LatencyLatestInfo build(Object data) { + List commandData = (List) data; + + String command = STRING.build(commandData.get(0)); + long timestamp = LONG.build(commandData.get(1)); + long lastEventLatency = LONG.build(commandData.get(2)); + long maxEventLatency = LONG.build(commandData.get(3)); + + return new LatencyLatestInfo(command, timestamp, lastEventLatency, maxEventLatency); + } + }; +} diff --git a/src/test/java/redis/clients/jedis/commands/jedis/ControlCommandsTest.java b/src/test/java/redis/clients/jedis/commands/jedis/ControlCommandsTest.java index df3fef6886..2cfff1e706 100644 --- a/src/test/java/redis/clients/jedis/commands/jedis/ControlCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/jedis/ControlCommandsTest.java @@ -36,6 +36,8 @@ import redis.clients.jedis.params.LolwutParams; import redis.clients.jedis.resps.CommandDocument; import redis.clients.jedis.resps.CommandInfo; +import redis.clients.jedis.resps.LatencyHistoryInfo; +import redis.clients.jedis.resps.LatencyLatestInfo; import redis.clients.jedis.util.AssertUtil; import redis.clients.jedis.util.KeyValue; import redis.clients.jedis.util.SafeEncoder; @@ -440,6 +442,23 @@ public void latencyDoctor() { assertNotNull(report); } + @Test + public void latencyLatest() { + Map report = jedis.latencyLatest(); + assertNotNull(report); + } + + @Test + public void latencyHistoryFork() { + List report = jedis.latencyHistory(Protocol.EventKeyword.FORK); + assertNotNull(report); + } + + @Test + public void latencyReset() { + assertTrue(jedis.latencyReset() >= 0); + } + @Test public void commandCount() { assertTrue(jedis.commandCount() > 100); From 4d0461b74561815387b7944b7d94fe567dd1571c Mon Sep 17 00:00:00 2001 From: carrot Date: Wed, 21 Feb 2024 23:00:14 +0300 Subject: [PATCH 2/3] add LatencyEvent class --- src/main/java/redis/clients/jedis/Jedis.java | 4 ++-- .../java/redis/clients/jedis/Protocol.java | 20 ---------------- .../clients/jedis/args/LatencyEvent.java | 24 +++++++++++++++++++ .../jedis/commands/ServerCommands.java | 6 ++--- .../commands/jedis/ControlCommandsTest.java | 3 ++- 5 files changed, 31 insertions(+), 26 deletions(-) create mode 100644 src/main/java/redis/clients/jedis/args/LatencyEvent.java diff --git a/src/main/java/redis/clients/jedis/Jedis.java b/src/main/java/redis/clients/jedis/Jedis.java index f70a09d271..8595a14de7 100644 --- a/src/main/java/redis/clients/jedis/Jedis.java +++ b/src/main/java/redis/clients/jedis/Jedis.java @@ -9287,13 +9287,13 @@ public Map latencyLatest() { return BuilderFactory.LATENCY_LATEST_RESPONSE.build(connection.getOne()); } - public List latencyHistory(EventKeyword event) { + public List latencyHistory(LatencyEvent event) { checkIsInMultiOrPipeline(); connection.sendCommand(new CommandArguments(LATENCY).add(HISTORY).add(event)); return BuilderFactory.LATENCY_HISTORY_RESPONSE.build(connection.getOne()); } - public long latencyReset(EventKeyword... events) { + public long latencyReset(LatencyEvent... events) { checkIsInMultiOrPipeline(); CommandArguments arguments = new CommandArguments(LATENCY).add(Keyword.RESET); Arrays.stream(events).forEach(arguments::add); diff --git a/src/main/java/redis/clients/jedis/Protocol.java b/src/main/java/redis/clients/jedis/Protocol.java index 8109760fa8..24830637fb 100644 --- a/src/main/java/redis/clients/jedis/Protocol.java +++ b/src/main/java/redis/clients/jedis/Protocol.java @@ -371,24 +371,4 @@ public byte[] getRaw() { return raw; } } - - public static enum EventKeyword implements Rawable { - ACTIVE_DEFRAG_CYCLE("active-defrag-cycle"), AOF_FSYNC_ALWAYS("aof-fsync-always"), AOF_STAT("aof-stat"), - AOF_REWRITE_DIFF_WRITE("aof-rewrite-diff-write"), AOF_RENAME("aof-rename"), AOF_WRITE("aof-write"), - AOF_WRITE_ACTIVE_CHILD("aof-write-active-child"), AOF_WRITE_ALONE("aof-write-alone"), - AOF_WRITE_PENDING_FSYNC("aof-write-pending-fsync"), COMMAND("command"), EXPIRE_CYCLE("expire-cycle"), - EVICTION_CYCLE("eviction-cycle"), EVICTION_DEL("eviction-del"), FAST_COMMAND("fast-command"), - FORK("fork"), RDB_UNLINK_TEMP_FILE("rdb-unlink-temp-file"); - - private final byte[] raw; - - EventKeyword(String s) { - raw = SafeEncoder.encode(s); - } - - @Override - public byte[] getRaw() { - return raw; - } - } } diff --git a/src/main/java/redis/clients/jedis/args/LatencyEvent.java b/src/main/java/redis/clients/jedis/args/LatencyEvent.java new file mode 100644 index 0000000000..be82e6c25e --- /dev/null +++ b/src/main/java/redis/clients/jedis/args/LatencyEvent.java @@ -0,0 +1,24 @@ +package redis.clients.jedis.args; + +import redis.clients.jedis.util.SafeEncoder; + +public enum LatencyEvent implements Rawable { + + ACTIVE_DEFRAG_CYCLE("active-defrag-cycle"), AOF_FSYNC_ALWAYS("aof-fsync-always"), AOF_STAT("aof-stat"), + AOF_REWRITE_DIFF_WRITE("aof-rewrite-diff-write"), AOF_RENAME("aof-rename"), AOF_WRITE("aof-write"), + AOF_WRITE_ACTIVE_CHILD("aof-write-active-child"), AOF_WRITE_ALONE("aof-write-alone"), + AOF_WRITE_PENDING_FSYNC("aof-write-pending-fsync"), COMMAND("command"), EXPIRE_CYCLE("expire-cycle"), + EVICTION_CYCLE("eviction-cycle"), EVICTION_DEL("eviction-del"), FAST_COMMAND("fast-command"), + FORK("fork"), RDB_UNLINK_TEMP_FILE("rdb-unlink-temp-file"); + + private final byte[] raw; + + LatencyEvent(String s) { + raw = SafeEncoder.encode(s); + } + + @Override + public byte[] getRaw() { + return raw; + } +} diff --git a/src/main/java/redis/clients/jedis/commands/ServerCommands.java b/src/main/java/redis/clients/jedis/commands/ServerCommands.java index 9115ea433f..3aeff1153b 100644 --- a/src/main/java/redis/clients/jedis/commands/ServerCommands.java +++ b/src/main/java/redis/clients/jedis/commands/ServerCommands.java @@ -1,7 +1,7 @@ package redis.clients.jedis.commands; -import redis.clients.jedis.Protocol; import redis.clients.jedis.args.FlushMode; +import redis.clients.jedis.args.LatencyEvent; import redis.clients.jedis.args.SaveMode; import redis.clients.jedis.exceptions.JedisException; import redis.clients.jedis.params.LolwutParams; @@ -255,7 +255,7 @@ default void shutdown(SaveMode saveMode) throws JedisException { Map latencyLatest(); - List latencyHistory(Protocol.EventKeyword events); + List latencyHistory(LatencyEvent events); - long latencyReset(Protocol.EventKeyword... events); + long latencyReset(LatencyEvent... events); } diff --git a/src/test/java/redis/clients/jedis/commands/jedis/ControlCommandsTest.java b/src/test/java/redis/clients/jedis/commands/jedis/ControlCommandsTest.java index 2cfff1e706..cb95a9489b 100644 --- a/src/test/java/redis/clients/jedis/commands/jedis/ControlCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/jedis/ControlCommandsTest.java @@ -30,6 +30,7 @@ import redis.clients.jedis.JedisMonitor; import redis.clients.jedis.Protocol; import redis.clients.jedis.args.ClientPauseMode; +import redis.clients.jedis.args.LatencyEvent; import redis.clients.jedis.exceptions.JedisDataException; import redis.clients.jedis.HostAndPorts; import redis.clients.jedis.params.CommandListFilterByParams; @@ -450,7 +451,7 @@ public void latencyLatest() { @Test public void latencyHistoryFork() { - List report = jedis.latencyHistory(Protocol.EventKeyword.FORK); + List report = jedis.latencyHistory(LatencyEvent.FORK); assertNotNull(report); } From 8f3bcc8d81a8a8abe179412f85f0b2ddce9fdf0b Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Thu, 22 Feb 2024 11:29:26 +0600 Subject: [PATCH 3/3] private constructor for LatencyEvent --- src/main/java/redis/clients/jedis/args/LatencyEvent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/redis/clients/jedis/args/LatencyEvent.java b/src/main/java/redis/clients/jedis/args/LatencyEvent.java index be82e6c25e..bd11d6a104 100644 --- a/src/main/java/redis/clients/jedis/args/LatencyEvent.java +++ b/src/main/java/redis/clients/jedis/args/LatencyEvent.java @@ -13,7 +13,7 @@ public enum LatencyEvent implements Rawable { private final byte[] raw; - LatencyEvent(String s) { + private LatencyEvent(String s) { raw = SafeEncoder.encode(s); }