mirror of https://github.com/valkey-io/valkey
[NEW] Introduce lttng based tracing (#2070)
## Introduce
In a production environment, it's quite challenging to figure out why a
Valkey is under high load. Right now, tools like INFO or slowlog can
offer some clues. But if the Valkey can't respond, we might not get any
information at all.
Usually, we have to rely on tools like `strace` or `perf` to find the
root cause. If we set up trace points in advance during the project
development, we can quickly pinpoint performance issues.
In this current PR, support has been added for all latency sampling
points. Also, information reporting for command execution has been
added. At the same time, it supports dynamically turning on or off the
information reporting as required. The trace feature is implemented
based on LTTng, and this capability is supported in projects like QEMU,
Ceph.
## How to use
Building Valkey with LTTng support:
```
USE_LTTNG=yes make
```
Open event report:
```
config set trace-events "sys server db cluster aof commands"
```
Events are classified as follows:
- sys (System-level operations)
- server (Server core logic)
- db (Database core operations)
- cluster (Cluster configuration operations)
- aof (AOF persistence operations)
- commands(Command execution information)
## How to trace
Enable lttng trace events dynamically:
```
~# lttng destroy valkey
~# lttng create valkey
~# lttng enable-event -u valkey:*
~# lttng track -u -p `pidof valkey-server`
~# lttng start
~# lttng stop
~# lttng view
```
Examples (a client run 'SET', another run 'keys'):
```
[15:30:19.334463706] (+0.000001243) libai valkey:command_call: { cpu_id = 15 }, { name = "set", duration = 0 }
[15:30:19.334465183] (+0.000001477) libai valkey:command_call: { cpu_id = 15 }, { name = "set", duration = 1 }
[15:30:19.334466516] (+0.000001333) libai valkey:command_call: { cpu_id = 15 }, { name = "set", duration = 0 }
[15:30:19.334467738] (+0.000001222) libai valkey:command_call: { cpu_id = 15 }, { name = "set", duration = 0 }
[15:30:19.334469105] (+0.000001367) libai valkey:command_call: { cpu_id = 15 }, { name = "set", duration = 1 }
[15:30:19.334470327] (+0.000001222) libai valkey:command_call: { cpu_id = 15 }, { name = "set", duration = 0 }
[15:30:19.369348485] (+0.034878158) libai valkey:command_call: { cpu_id = 15 }, { name = "keys", duration = 34874 }
[15:30:19.369698322] (+0.000349837) libai valkey:command_call: { cpu_id = 15 }, { name = "set", duration = 4 }
[15:30:19.369702327] (+0.000004005) libai valkey:command_call: { cpu_id = 15 }, { name = "set", duration = 2 }
```
Then we can use another script to analyze topN slow commands and other
system
level events.
About performance overhead (valkey-benchmark -t get -n 1000000 --threads
4):
1> no lttng builtin: 285632.69 requests per second
2> lttng builtin, no trace: 285551.09 requests per second (almost 0
overhead)
3> lttng builtin, trace commands: 266595.59 requests per second (about
~6.6 overhead)
Generally valkey-server would not run in full utilization, the overhead
is acceptable.
## Problem analysis
Add prot and conn field into trace command
Run benchmark tool:
```
GET: rps=227428.0 (overall: 222756.2) avg_msec=0.114 (overall: 0.117)
GET: rps=225248.0 (overall: 223005.2) avg_msec=0.115 (overall: 0.117)
GET: rps=167474.1 (overall: 217942.2) avg_msec=0.193 (overall: 0.122) --> performance drop
GET: rps=220192.0 (overall: 218129.5) avg_msec=0.118 (overall: 0.122)
GET: rps=222868.0 (overall: 218493.7) avg_msec=0.117 (overall: 0.121)
```
Run another 'keys *' command in another connection, lead benchmark
performance
drop.
At the same time, lttng traces events:
```
[21:16:30.420997167] (+0.000004064) zhenwei valkey:command_call: { cpu_id = 6 }, { prot = "tcp", conn = "127.0.0.1:6379-127.0.0.1:54668", name = "get", duration = 1 }
[21:16:30.421001262] (+0.000004095) zhenwei valkey:command_call: { cpu_id = 6 }, { prot = "tcp", conn = "127.0.0.1:6379-127.0.0.1:54782", name = "get", duration = 1 }
[21:16:30.485562459] (+0.064561197) zhenwei valkey:command_call: { cpu_id = 6 }, { prot = "tcp", conn = "127.0.0.1:6379-127.0.0.1:54386", name = "keys", duration = 64551 } --> root cause
[21:16:30.485583101] (+0.000020642) zhenwei valkey:command_call: { cpu_id = 6 }, { prot = "tcp", conn = "127.0.0.1:6379-127.0.0.1:54522", name = "get", duration = 1 }
[21:16:30.485763891] (+0.000180790) zhenwei valkey:command_call: { cpu_id = 6 }, { prot = "tcp", conn = "127.0.0.1:6379-127.0.0.1:54542", name = "get", duration = 1 }
[21:16:30.485766451] (+0.000002560) zhenwei valkey:command_call: { cpu_id = 6 }, { prot = "tcp", conn = "127.0.0.1:6379-127.0.0.1:54438", name = "get", duration = 1 }
```
From this change, we can see that connection
127.0.0.1:6379-127.0.0.1:54386
affects other connections.
---------
Signed-off-by: zhenwei pi <pizhenwei@bytedance.com>
Signed-off-by: artikell <739609084@qq.com>
Signed-off-by: skyfirelee <739609084@qq.com>
Co-authored-by: zhenwei pi <pizhenwei@bytedance.com>
This commit is contained in:
parent
838ba44cd6
commit
1941d28acd
|
|
@ -827,6 +827,47 @@ jobs:
|
|||
if: true && !contains(github.event.inputs.skiptests, 'unittest')
|
||||
run: ./src/valkey-unit-tests
|
||||
|
||||
test-ubuntu-lttng:
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
(github.event_name == 'workflow_dispatch' ||
|
||||
(github.event_name == 'schedule' && github.repository == 'valkey-io/valkey') ||
|
||||
(github.event_name == 'pull_request' && (contains(github.event.pull_request.labels.*.name, 'run-extra-tests') || github.event.pull_request.base.ref != 'unstable'))) &&
|
||||
!contains(github.event.inputs.skipjobs, 'lttng')
|
||||
timeout-minutes: 1440
|
||||
steps:
|
||||
- name: prep
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
run: |
|
||||
echo "GITHUB_REPOSITORY=${{github.event.inputs.use_repo}}" >> $GITHUB_ENV
|
||||
echo "GITHUB_HEAD_REF=${{github.event.inputs.use_git_ref}}" >> $GITHUB_ENV
|
||||
echo "skipjobs: ${{github.event.inputs.skipjobs}}"
|
||||
echo "skiptests: ${{github.event.inputs.skiptests}}"
|
||||
echo "test_args: ${{github.event.inputs.test_args}}"
|
||||
echo "cluster_test_args: ${{github.event.inputs.cluster_test_args}}"
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
with:
|
||||
repository: ${{ env.GITHUB_REPOSITORY }}
|
||||
ref: ${{ env.GITHUB_HEAD_REF }}
|
||||
- name: make
|
||||
run: |
|
||||
sudo apt-get update && sudo apt-get install lttng-tools lttng-modules-dkms liblttng-ust-dev
|
||||
make -j4 USE_LTTNG=yes
|
||||
- name: testprep
|
||||
run: sudo apt-get install tcl8.6 tclx
|
||||
- name: test
|
||||
if: true && !contains(github.event.inputs.skiptests, 'valkey')
|
||||
run: ./runtest ${{ github.event_name != 'pull_request' && '--accurate' || '' }} --verbose --dump-logs ${{github.event.inputs.test_args}}
|
||||
- name: module api test
|
||||
if: true && !contains(github.event.inputs.skiptests, 'modules')
|
||||
run: CFLAGS='-Werror' ./runtest-moduleapi --verbose --dump-logs ${{github.event.inputs.test_args}}
|
||||
- name: sentinel tests
|
||||
if: true && !contains(github.event.inputs.skiptests, 'sentinel')
|
||||
run: ./runtest-sentinel ${{github.event.inputs.cluster_test_args}}
|
||||
- name: cluster tests
|
||||
if: true && !contains(github.event.inputs.skiptests, 'cluster')
|
||||
run: ./runtest-cluster ${{github.event.inputs.cluster_test_args}}
|
||||
|
||||
test-rpm-distros-jemalloc:
|
||||
if: |
|
||||
(github.event_name == 'workflow_dispatch' ||
|
||||
|
|
|
|||
|
|
@ -104,6 +104,13 @@ set(VALKEY_SERVER_SRCS
|
|||
${CMAKE_SOURCE_DIR}/src/lua/function_lua.c
|
||||
${CMAKE_SOURCE_DIR}/src/lua/engine_lua.c
|
||||
${CMAKE_SOURCE_DIR}/src/lua/debug_lua.c
|
||||
${CMAKE_SOURCE_DIR}/src/trace/trace.c
|
||||
${CMAKE_SOURCE_DIR}/src/trace/trace_aof.c
|
||||
${CMAKE_SOURCE_DIR}/src/trace/trace_commands.c
|
||||
${CMAKE_SOURCE_DIR}/src/trace/trace_db.c
|
||||
${CMAKE_SOURCE_DIR}/src/trace/trace_cluster.c
|
||||
${CMAKE_SOURCE_DIR}/src/trace/trace_server.c
|
||||
${CMAKE_SOURCE_DIR}/src/trace/trace_bgsave.c
|
||||
${CMAKE_SOURCE_DIR}/src/commands.c
|
||||
${CMAKE_SOURCE_DIR}/src/strl.c
|
||||
${CMAKE_SOURCE_DIR}/src/connection.c
|
||||
|
|
|
|||
|
|
@ -14,3 +14,4 @@ sha1.*
|
|||
sha256.*
|
||||
siphash.c
|
||||
strl.c
|
||||
trace/trace_*
|
||||
14
src/Makefile
14
src/Makefile
|
|
@ -295,6 +295,11 @@ ifeq ($(MALLOC),jemalloc)
|
|||
FINAL_LIBS := ../deps/jemalloc/lib/libjemalloc.a $(FINAL_LIBS)
|
||||
endif
|
||||
|
||||
ifeq ($(USE_LTTNG),yes)
|
||||
FINAL_CFLAGS+=-DUSE_LTTNG
|
||||
FINAL_LIBS += -llttng-ust
|
||||
endif
|
||||
|
||||
# LIBSSL & LIBCRYPTO
|
||||
LIBSSL_LIBS=
|
||||
LIBSSL_PKGCONFIG := $(shell $(PKG_CONFIG) --exists libssl && echo $$?)
|
||||
|
|
@ -386,7 +391,7 @@ else
|
|||
MAYBE_UNINSTALL_REDIS_SYMLINK=
|
||||
endif
|
||||
|
||||
SERVER_CC=$(QUIET_CC)$(CC) $(FINAL_CFLAGS)
|
||||
SERVER_CC=$(QUIET_CC)$(CC) $(FINAL_CFLAGS) -I.
|
||||
SERVER_AR=$(QUIET_AR)$(AR)
|
||||
SERVER_LD=$(QUIET_LINK)$(CC) $(FINAL_LDFLAGS)
|
||||
ENGINE_INSTALL=$(QUIET_INSTALL)$(INSTALL)
|
||||
|
|
@ -417,7 +422,9 @@ endif
|
|||
ENGINE_NAME=valkey
|
||||
SERVER_NAME=$(ENGINE_NAME)-server$(PROG_SUFFIX)
|
||||
ENGINE_SENTINEL_NAME=$(ENGINE_NAME)-sentinel$(PROG_SUFFIX)
|
||||
ENGINE_TRACE_OBJ=trace/trace.o trace/trace_commands.o trace/trace_db.o trace/trace_bgsave.o trace/trace_cluster.o trace/trace_server.o trace/trace_aof.o
|
||||
ENGINE_SERVER_OBJ=threads_mngr.o adlist.o quicklist.o ae.o anet.o dict.o hashtable.o kvstore.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o memory_prefetch.o io_threads.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o cluster_legacy.o cluster_slot_stats.o crc16.o endianconv.o commandlog.o eval.o bio.o rio.o rand.o memtest.o syscheck.o crcspeed.o crccombine.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o valkey-check-rdb.o valkey-check-aof.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o allocator_defrag.o defrag.o siphash.o rax.o t_stream.o listpack.o localtime.o lolwut.o lolwut5.o lolwut6.o acl.o tracking.o socket.o tls.o sha256.o timeout.o setcpuaffinity.o monotonic.o mt19937-64.o resp_parser.o call_reply.o script.o functions.o commands.o strl.o connection.o unix.o logreqres.o rdma.o scripting_engine.o lua/script_lua.o lua/function_lua.o lua/engine_lua.o lua/debug_lua.o
|
||||
ENGINE_SERVER_OBJ+=$(ENGINE_TRACE_OBJ)
|
||||
ENGINE_CLI_NAME=$(ENGINE_NAME)-cli$(PROG_SUFFIX)
|
||||
ENGINE_CLI_OBJ=anet.o adlist.o dict.o valkey-cli.o zmalloc.o release.o ae.o serverassert.o crcspeed.o crccombine.o crc64.o siphash.o crc16.o monotonic.o cli_common.o mt19937-64.o strl.o cli_commands.o sds.o util.o sha256.o
|
||||
ENGINE_BENCHMARK_NAME=$(ENGINE_NAME)-benchmark$(PROG_SUFFIX)
|
||||
|
|
@ -541,6 +548,9 @@ DEP = $(ENGINE_SERVER_OBJ:%.o=%.d) $(ENGINE_CLI_OBJ:%.o=%.d) $(ENGINE_BENCHMARK_
|
|||
lua/%.o: lua/%.c .make-prerequisites
|
||||
$(SERVER_CC) -MMD -o $@ -c $<
|
||||
|
||||
trace/%.o: trace/%.c .make-prerequisites
|
||||
$(SERVER_CC) -Itrace -MMD -o $@ -c $<
|
||||
|
||||
unit/%.o: unit/%.c .make-prerequisites
|
||||
$(SERVER_CC) -MMD -o $@ -c $<
|
||||
|
||||
|
|
@ -564,7 +574,7 @@ endif
|
|||
commands.c: $(COMMANDS_DEF_FILENAME).def
|
||||
|
||||
clean:
|
||||
rm -rf $(SERVER_NAME) $(ENGINE_SENTINEL_NAME) $(ENGINE_CLI_NAME) $(ENGINE_BENCHMARK_NAME) $(ENGINE_CHECK_RDB_NAME) $(ENGINE_CHECK_AOF_NAME) $(ENGINE_UNIT_TESTS) $(ENGINE_LIB_NAME) unit/*.o unit/*.d lua/*.o lua/*.d *.o *.gcda *.gcno *.gcov valkey.info lcov-html Makefile.dep *.so
|
||||
rm -rf $(SERVER_NAME) $(ENGINE_SENTINEL_NAME) $(ENGINE_CLI_NAME) $(ENGINE_BENCHMARK_NAME) $(ENGINE_CHECK_RDB_NAME) $(ENGINE_CHECK_AOF_NAME) $(ENGINE_UNIT_TESTS) $(ENGINE_LIB_NAME) unit/*.o unit/*.d lua/*.o lua/*.d trace/*.o trace/*.d *.o *.gcda *.gcno *.gcov valkey.info lcov-html Makefile.dep *.so
|
||||
rm -f $(DEP)
|
||||
|
||||
.PHONY: clean
|
||||
|
|
|
|||
|
|
@ -1129,12 +1129,16 @@ void flushAppendOnlyFile(int force) {
|
|||
* useful for graphing / monitoring purposes. */
|
||||
if (sync_in_progress) {
|
||||
latencyAddSampleIfNeeded("aof-write-pending-fsync", latency);
|
||||
latencyTraceIfNeeded(aof, aof_write_pending_fsync, latency);
|
||||
} else if (hasActiveChildProcess()) {
|
||||
latencyAddSampleIfNeeded("aof-write-active-child", latency);
|
||||
latencyTraceIfNeeded(aof, aof_write_active_child, latency);
|
||||
} else {
|
||||
latencyAddSampleIfNeeded("aof-write-alone", latency);
|
||||
latencyTraceIfNeeded(aof, aof_write_alone, latency);
|
||||
}
|
||||
latencyAddSampleIfNeeded("aof-write", latency);
|
||||
latencyTraceIfNeeded(aof, aof_write, latency);
|
||||
|
||||
/* We performed the write so reset the postponed flush sentinel to zero. */
|
||||
server.aof_flush_postponed_start = 0;
|
||||
|
|
@ -1248,6 +1252,8 @@ try_fsync:
|
|||
}
|
||||
latencyEndMonitor(latency);
|
||||
latencyAddSampleIfNeeded("aof-fsync-always", latency);
|
||||
latencyTraceIfNeeded(aof, aof_fsync_always, latency);
|
||||
|
||||
server.aof_last_incr_fsync_offset = server.aof_last_incr_size;
|
||||
server.aof_last_fsync = server.mstime;
|
||||
atomic_store_explicit(&server.fsynced_reploff_pending, server.primary_repl_offset, memory_order_relaxed);
|
||||
|
|
@ -2501,6 +2507,7 @@ off_t getAppendOnlyFileSize(sds filename, int *status) {
|
|||
}
|
||||
latencyEndMonitor(latency);
|
||||
latencyAddSampleIfNeeded("aof-fstat", latency);
|
||||
latencyTraceIfNeeded(aof, aof_fstat, latency);
|
||||
sdsfree(aof_filepath);
|
||||
return size;
|
||||
}
|
||||
|
|
@ -2577,6 +2584,7 @@ void backgroundRewriteDoneHandler(int exitcode, int bysignal) {
|
|||
}
|
||||
latencyEndMonitor(latency);
|
||||
latencyAddSampleIfNeeded("aof-rename", latency);
|
||||
latencyTraceIfNeeded(aof, aof_rename, latency);
|
||||
serverLog(LL_NOTICE, "Successfully renamed the temporary AOF base file %s into %s", tmpfile, new_base_filename);
|
||||
|
||||
/* Rename the temporary incr aof file to 'new_incr_filename'. */
|
||||
|
|
@ -2603,6 +2611,7 @@ void backgroundRewriteDoneHandler(int exitcode, int bysignal) {
|
|||
}
|
||||
latencyEndMonitor(latency);
|
||||
latencyAddSampleIfNeeded("aof-rename", latency);
|
||||
latencyTraceIfNeeded(aof, aof_rename, latency);
|
||||
serverLog(LL_NOTICE, "Successfully renamed the temporary AOF incr file %s into %s", temp_incr_aof_name,
|
||||
new_incr_filename);
|
||||
sdsfree(temp_incr_filepath);
|
||||
|
|
|
|||
|
|
@ -148,7 +148,8 @@ void updateStatsOnUnblock(client *c, long blocked_us, long reply_us, int failed_
|
|||
commandlogPushCurrentCommand(c, c->lastcmd);
|
||||
c->duration = 0;
|
||||
/* Log the reply duration event. */
|
||||
latencyAddSampleIfNeeded("command-unblocking", reply_us / 1000);
|
||||
latencyAddSampleIfNeeded("command-unblocking", reply_us);
|
||||
latencyTraceIfNeeded(server, command_unblocking, reply_us);
|
||||
}
|
||||
|
||||
/* This function is called in the beforeSleep() function of the event loop
|
||||
|
|
|
|||
|
|
@ -857,7 +857,7 @@ int clusterSaveConfig(int do_fsync) {
|
|||
}
|
||||
latencyEndMonitor(latency);
|
||||
latencyAddSampleIfNeeded("cluster-config-open", latency);
|
||||
|
||||
latencyTraceIfNeeded(cluster, cluster_config_open, latency);
|
||||
latencyStartMonitor(latency);
|
||||
while (offset < content_size) {
|
||||
written_bytes = write(fd, ci + offset, content_size - offset);
|
||||
|
|
@ -871,7 +871,7 @@ int clusterSaveConfig(int do_fsync) {
|
|||
}
|
||||
latencyEndMonitor(latency);
|
||||
latencyAddSampleIfNeeded("cluster-config-write", latency);
|
||||
|
||||
latencyTraceIfNeeded(cluster, cluster_config_write, latency);
|
||||
if (do_fsync) {
|
||||
latencyStartMonitor(latency);
|
||||
server.cluster->todo_before_sleep &= ~CLUSTER_TODO_FSYNC_CONFIG;
|
||||
|
|
@ -881,6 +881,7 @@ int clusterSaveConfig(int do_fsync) {
|
|||
}
|
||||
latencyEndMonitor(latency);
|
||||
latencyAddSampleIfNeeded("cluster-config-fsync", latency);
|
||||
latencyTraceIfNeeded(cluster, cluster_config_fsync, latency);
|
||||
}
|
||||
|
||||
latencyStartMonitor(latency);
|
||||
|
|
@ -890,7 +891,7 @@ int clusterSaveConfig(int do_fsync) {
|
|||
}
|
||||
latencyEndMonitor(latency);
|
||||
latencyAddSampleIfNeeded("cluster-config-rename", latency);
|
||||
|
||||
latencyTraceIfNeeded(cluster, cluster_config_rename, latency);
|
||||
if (do_fsync) {
|
||||
latencyStartMonitor(latency);
|
||||
if (fsyncFileDir(server.cluster_configfile) == -1) {
|
||||
|
|
@ -899,6 +900,7 @@ int clusterSaveConfig(int do_fsync) {
|
|||
}
|
||||
latencyEndMonitor(latency);
|
||||
latencyAddSampleIfNeeded("cluster-config-dir-fsync", latency);
|
||||
latencyTraceIfNeeded(cluster, cluster_config_dir_fsync, latency);
|
||||
}
|
||||
retval = C_OK; /* If we reached this point, everything is fine. */
|
||||
|
||||
|
|
@ -908,12 +910,14 @@ cleanup:
|
|||
close(fd);
|
||||
latencyEndMonitor(latency);
|
||||
latencyAddSampleIfNeeded("cluster-config-close", latency);
|
||||
latencyTraceIfNeeded(cluster, cluster_config_close, latency);
|
||||
}
|
||||
if (retval == C_ERR) {
|
||||
latencyStartMonitor(latency);
|
||||
unlink(tmpfilename);
|
||||
latencyEndMonitor(latency);
|
||||
latencyAddSampleIfNeeded("cluster-config-unlink", latency);
|
||||
latencyTraceIfNeeded(cluster, cluster_config_unlink, latency);
|
||||
}
|
||||
sdsfree(tmpfilename);
|
||||
sdsfree(ci);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include "ae.h"
|
||||
|
|
@ -41,6 +42,11 @@
|
|||
#define CONN_INFO_LEN 32
|
||||
#define CONN_ADDR_STR_LEN 128 /* Similar to INET6_ADDRSTRLEN, hoping to handle other protocols. */
|
||||
|
||||
#define NET_HOST_STR_LEN 256 /* Longest valid hostname */
|
||||
#define NET_IP_STR_LEN 46 /* INET6_ADDRSTRLEN is 46, but we need to be sure */
|
||||
#define NET_ADDR_STR_LEN (NET_IP_STR_LEN + 32) /* Must be enough for ip:port */
|
||||
#define NET_HOST_PORT_STR_LEN (NET_HOST_STR_LEN + 32) /* Must be enough for hostname:port */
|
||||
|
||||
struct aeEventLoop;
|
||||
typedef struct connection connection;
|
||||
typedef struct connListener connListener;
|
||||
|
|
@ -58,6 +64,14 @@ typedef enum {
|
|||
#define CONN_FLAG_WRITE_BARRIER (1 << 1) /* Write barrier requested */
|
||||
#define CONN_FLAG_ALLOW_ACCEPT_OFFLOAD (1 << 2) /* Connection accept can be offloaded to IO threads. */
|
||||
|
||||
typedef enum {
|
||||
CONN_TYPE_ID_INVALID = 0,
|
||||
CONN_TYPE_ID_SOCKET,
|
||||
CONN_TYPE_ID_UNIX,
|
||||
CONN_TYPE_ID_TLS,
|
||||
CONN_TYPE_ID_RDMA,
|
||||
} ConnectionTypeId;
|
||||
|
||||
#define CONN_TYPE_SOCKET "tcp"
|
||||
#define CONN_TYPE_UNIX "unix"
|
||||
#define CONN_TYPE_TLS "tls"
|
||||
|
|
@ -68,6 +82,7 @@ typedef void (*ConnectionCallbackFunc)(struct connection *conn);
|
|||
|
||||
typedef struct ConnectionType {
|
||||
/* connection type */
|
||||
int (*get_type_id)(struct connection *conn);
|
||||
const char *(*get_type)(struct connection *conn);
|
||||
|
||||
/* connection type initialize & finalize & configure */
|
||||
|
|
@ -295,6 +310,13 @@ static inline const char *connGetType(connection *conn) {
|
|||
return conn->type->get_type(conn);
|
||||
}
|
||||
|
||||
static inline int connGetTypeId(connection *conn) {
|
||||
if (!conn || conn->type->get_type_id == NULL) {
|
||||
return CONN_TYPE_ID_INVALID;
|
||||
}
|
||||
return conn->type->get_type_id(conn);
|
||||
}
|
||||
|
||||
static inline int connLastErrorRetryable(connection *conn) {
|
||||
return conn->last_errno == EINTR;
|
||||
}
|
||||
|
|
|
|||
1
src/db.c
1
src/db.c
|
|
@ -1816,6 +1816,7 @@ void deleteExpiredKeyAndPropagateWithDictIndex(serverDb *db, robj *keyobj, int d
|
|||
dbGenericDeleteWithDictIndex(db, keyobj, server.lazyfree_lazy_expire, DB_FLAG_KEY_EXPIRED, dict_index);
|
||||
latencyEndMonitor(expire_latency);
|
||||
latencyAddSampleIfNeeded("expire-del", expire_latency);
|
||||
latencyTraceIfNeeded(db, expire_del, expire_latency);
|
||||
notifyKeyspaceEvent(NOTIFY_EXPIRED, "expired", keyobj, db->id);
|
||||
signalModifiedKey(NULL, db, keyobj);
|
||||
propagateDeletion(db, keyobj, server.lazyfree_lazy_expire);
|
||||
|
|
|
|||
|
|
@ -1187,7 +1187,7 @@ static long long activeDefragTimeProc(struct aeEventLoop *eventLoop, long long i
|
|||
|
||||
latencyEndMonitor(latency);
|
||||
latencyAddSampleIfNeeded("active-defrag-cycle", latency);
|
||||
|
||||
latencyTraceIfNeeded(db, active_defrag_cycle, latency);
|
||||
if (haveMoreWork) {
|
||||
return computeDelayMs(endtime);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -671,6 +671,7 @@ int performEvictions(void) {
|
|||
dbGenericDelete(db, keyobj, server.lazyfree_lazy_eviction, DB_FLAG_KEY_EVICTED);
|
||||
latencyEndMonitor(eviction_latency);
|
||||
latencyAddSampleIfNeeded("eviction-del", eviction_latency);
|
||||
latencyTraceIfNeeded(db, eviction_del, eviction_latency);
|
||||
delta -= (long long)zmalloc_used_memory();
|
||||
mem_freed += delta;
|
||||
server.stat_evictedkeys++;
|
||||
|
|
@ -734,10 +735,12 @@ cant_free:
|
|||
}
|
||||
latencyEndMonitor(lazyfree_latency);
|
||||
latencyAddSampleIfNeeded("eviction-lazyfree", lazyfree_latency);
|
||||
latencyTraceIfNeeded(db, eviction_lazyfree, lazyfree_latency);
|
||||
}
|
||||
|
||||
latencyEndMonitor(latency);
|
||||
latencyAddSampleIfNeeded("eviction-cycle", latency);
|
||||
latencyTraceIfNeeded(db, eviction_cycle, latency);
|
||||
|
||||
update_metrics:
|
||||
if (result == EVICT_RUNNING || result == EVICT_FAIL) {
|
||||
|
|
|
|||
|
|
@ -359,7 +359,8 @@ void activeExpireCycle(int type) {
|
|||
|
||||
elapsed = ustime() - start;
|
||||
server.stat_expire_cycle_time_used += elapsed;
|
||||
latencyAddSampleIfNeeded("expire-cycle", elapsed / 1000);
|
||||
latencyAddSampleIfNeeded("expire-cycle", elapsed);
|
||||
latencyTraceIfNeeded(db, expire_cycle, elapsed);
|
||||
|
||||
/* Update our estimate of keys existing but yet to be expired.
|
||||
* Running average with this sample accounting for 5%. */
|
||||
|
|
|
|||
|
|
@ -76,7 +76,8 @@ void latencyMonitorInit(void) {
|
|||
* This function is usually called via latencyAddSampleIfNeeded(), that
|
||||
* is a macro that only adds the sample if the latency is higher than
|
||||
* server.latency_monitor_threshold. */
|
||||
void latencyAddSample(const char *event, mstime_t latency) {
|
||||
void latencyAddSample(const char *event, ustime_t latency_us) {
|
||||
mstime_t latency = latency_us / 1000;
|
||||
struct latencyTimeSeries *ts = dictFetchValue(server.latency_events, event);
|
||||
time_t now = time(NULL);
|
||||
int prev;
|
||||
|
|
|
|||
|
|
@ -34,8 +34,14 @@
|
|||
#ifndef __LATENCY_H
|
||||
#define __LATENCY_H
|
||||
|
||||
#include "trace/trace.h"
|
||||
|
||||
#define LATENCY_TS_LEN 160 /* History length for every monitored event. */
|
||||
|
||||
#ifndef LATENCY_TRACE_SWITCH
|
||||
#define LATENCY_TRACE_SWITCH 0
|
||||
#endif
|
||||
|
||||
/* Representation of a latency sample: the sampling time and the latency
|
||||
* observed in milliseconds. */
|
||||
struct latencySample {
|
||||
|
|
@ -64,14 +70,14 @@ struct latencyStats {
|
|||
};
|
||||
|
||||
void latencyMonitorInit(void);
|
||||
void latencyAddSample(const char *event, mstime_t latency);
|
||||
void latencyAddSample(const char *event, ustime_t latency);
|
||||
|
||||
/* Latency monitoring macros. */
|
||||
|
||||
/* Start monitoring an event. We just set the current time. */
|
||||
#define latencyStartMonitor(var) \
|
||||
if (server.latency_monitor_threshold) { \
|
||||
var = mstime(); \
|
||||
if (server.latency_monitor_threshold || LATENCY_TRACE_SWITCH) { \
|
||||
var = ustime(); \
|
||||
} else { \
|
||||
var = 0; \
|
||||
}
|
||||
|
|
@ -79,13 +85,13 @@ void latencyAddSample(const char *event, mstime_t latency);
|
|||
/* End monitoring an event, compute the difference with the current time
|
||||
* to check the amount of time elapsed. */
|
||||
#define latencyEndMonitor(var) \
|
||||
if (server.latency_monitor_threshold) { \
|
||||
var = mstime() - var; \
|
||||
if (server.latency_monitor_threshold || LATENCY_TRACE_SWITCH) { \
|
||||
var = ustime() - var; \
|
||||
}
|
||||
|
||||
/* Add the sample only if the elapsed time is >= to the configured threshold. */
|
||||
#define latencyAddSampleIfNeeded(event, var) \
|
||||
if (server.latency_monitor_threshold && (var) >= server.latency_monitor_threshold) latencyAddSample((event), (var));
|
||||
if (server.latency_monitor_threshold && (var) >= server.latency_monitor_threshold * 1000) latencyAddSample((event), (var));
|
||||
|
||||
/* Remove time from a nested event. */
|
||||
#define latencyRemoveNestedEvent(event_var, nested_var) event_var += nested_var;
|
||||
|
|
|
|||
|
|
@ -7717,7 +7717,7 @@ void VM__Assert(const char *estr, const char *file, int line) {
|
|||
* command. The call is skipped if the latency is smaller than the configured
|
||||
* latency-monitor-threshold. */
|
||||
void VM_LatencyAddSample(const char *event, mstime_t latency) {
|
||||
latencyAddSampleIfNeeded(event, latency);
|
||||
latencyAddSampleIfNeeded(event, latency * 1000);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -1690,11 +1690,12 @@ void acceptCommonHandler(connection *conn, struct ClientFlags flags, char *ip) {
|
|||
client *c;
|
||||
UNUSED(ip);
|
||||
|
||||
if (connGetState(conn) != CONN_STATE_ACCEPTING) {
|
||||
char addr[NET_ADDR_STR_LEN] = {0};
|
||||
char laddr[NET_ADDR_STR_LEN] = {0};
|
||||
connFormatAddr(conn, addr, sizeof(addr), 1);
|
||||
connFormatAddr(conn, laddr, sizeof(addr), 0);
|
||||
|
||||
if (connGetState(conn) != CONN_STATE_ACCEPTING) {
|
||||
serverLog(LL_VERBOSE, "Accepted client connection in error state: %s (addr=%s laddr=%s)",
|
||||
connGetLastError(conn), addr, laddr);
|
||||
connClose(conn);
|
||||
|
|
@ -1727,10 +1728,6 @@ void acceptCommonHandler(connection *conn, struct ClientFlags flags, char *ip) {
|
|||
|
||||
/* Create connection and client */
|
||||
if ((c = createClient(conn)) == NULL) {
|
||||
char addr[NET_ADDR_STR_LEN] = {0};
|
||||
char laddr[NET_ADDR_STR_LEN] = {0};
|
||||
connFormatAddr(conn, addr, sizeof(addr), 1);
|
||||
connFormatAddr(conn, laddr, sizeof(addr), 0);
|
||||
serverLog(LL_WARNING, "Error registering fd event for the new client connection: %s (addr=%s laddr=%s)",
|
||||
connGetLastError(conn), addr, laddr);
|
||||
connClose(conn); /* May be already closed, just ignore errors */
|
||||
|
|
|
|||
|
|
@ -3478,6 +3478,7 @@ static void backgroundSaveDoneHandlerDisk(int exitcode, int bysignal, time_t sav
|
|||
rdbRemoveTempFile(server.child_pid, 0);
|
||||
latencyEndMonitor(latency);
|
||||
latencyAddSampleIfNeeded("rdb-unlink-temp-file", latency);
|
||||
latencyTraceIfNeeded(bgsave, rdb_unlink_temp_file, latency);
|
||||
/* SIGUSR1 is whitelisted, so we have a way to kill a child without
|
||||
* triggering an error condition. */
|
||||
if (bysignal != SIGUSR1) server.lastbgsave_status = C_ERR;
|
||||
|
|
|
|||
|
|
@ -1520,6 +1520,12 @@ static const char *connRdmaGetType(connection *conn) {
|
|||
return CONN_TYPE_RDMA;
|
||||
}
|
||||
|
||||
static int connRdmaGetTypeId(connection *conn) {
|
||||
UNUSED(conn);
|
||||
|
||||
return CONN_TYPE_ID_RDMA;
|
||||
}
|
||||
|
||||
static int rdmaServer(char *err, int port, char *bindaddr, int af, rdma_listener *rdma_listener) {
|
||||
int ret = ANET_OK, rv, afonly = 1;
|
||||
char _port[6]; /* strlen("65535") */
|
||||
|
|
@ -1814,6 +1820,7 @@ static void updateRdmaState(struct connection *conn) {
|
|||
|
||||
static ConnectionType CT_RDMA = {
|
||||
/* connection type */
|
||||
.get_type_id = connRdmaGetTypeId,
|
||||
.get_type = connRdmaGetType,
|
||||
|
||||
/* connection type initialize & finalize & configure */
|
||||
|
|
|
|||
|
|
@ -822,7 +822,7 @@ void sentinelRunPendingScripts(void) {
|
|||
sj->flags |= SENTINEL_SCRIPT_RUNNING;
|
||||
sj->start_time = mstime();
|
||||
sj->retry_num++;
|
||||
pid = fork();
|
||||
pid = valkey_fork();
|
||||
|
||||
if (pid == -1) {
|
||||
/* Parent (fork error).
|
||||
|
|
|
|||
25
src/server.c
25
src/server.c
|
|
@ -52,6 +52,8 @@
|
|||
#include "lua/debug_lua.h"
|
||||
#include "eval.h"
|
||||
|
||||
#include "trace/trace_commands.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
#include <sys/wait.h>
|
||||
|
|
@ -1743,6 +1745,7 @@ void whileBlockedCron(void) {
|
|||
|
||||
latencyEndMonitor(latency);
|
||||
latencyAddSampleIfNeeded("while-blocked-cron", latency);
|
||||
latencyTraceIfNeeded(server, while_blocked_cron, latency);
|
||||
|
||||
/* We received a SIGTERM during loading, shutting down here in a safe way,
|
||||
* as it isn't ok doing so inside the signal handler. */
|
||||
|
|
@ -1885,7 +1888,9 @@ void beforeSleep(struct aeEventLoop *eventLoop) {
|
|||
if (server.aof_state == AOF_ON || server.aof_state == AOF_WAIT_REWRITE) flushAppendOnlyFile(0);
|
||||
|
||||
/* Record time consumption of AOF writing. */
|
||||
durationAddSample(EL_DURATION_TYPE_AOF, getMonotonicUs() - aof_start_time);
|
||||
monotime aof_duration = getMonotonicUs() - aof_start_time;
|
||||
durationAddSample(EL_DURATION_TYPE_AOF, aof_duration);
|
||||
latencyTraceIfNeeded(aof, aof_flush, aof_duration);
|
||||
|
||||
/* Update the fsynced replica offset.
|
||||
* If an initial rewrite is in progress then not all data is guaranteed to have actually been
|
||||
|
|
@ -1929,9 +1934,11 @@ void beforeSleep(struct aeEventLoop *eventLoop) {
|
|||
if (server.el_start > 0) {
|
||||
monotime el_duration = getMonotonicUs() - server.el_start;
|
||||
durationAddSample(EL_DURATION_TYPE_EL, el_duration);
|
||||
latencyTraceIfNeeded(server, eventloop, el_duration);
|
||||
}
|
||||
server.el_cron_duration += duration_before_aof + duration_after_write;
|
||||
durationAddSample(EL_DURATION_TYPE_CRON, server.el_cron_duration);
|
||||
latencyTraceIfNeeded(server, eventloop_cron, server.el_cron_duration);
|
||||
server.el_cron_duration = 0;
|
||||
/* Record max command count per cycle. */
|
||||
if (server.stat_numcommands > server.el_cmd_cnt_start) {
|
||||
|
|
@ -1973,6 +1980,7 @@ void afterSleep(struct aeEventLoop *eventLoop, int numevents) {
|
|||
moduleFireServerEvent(VALKEYMODULE_EVENT_EVENTLOOP, VALKEYMODULE_SUBEVENT_EVENTLOOP_AFTER_SLEEP, NULL);
|
||||
latencyEndMonitor(latency);
|
||||
latencyAddSampleIfNeeded("module-acquire-GIL", latency);
|
||||
latencyTraceIfNeeded(server, module_acquire_gil, latency);
|
||||
}
|
||||
/* Set the eventloop start time. */
|
||||
server.el_start = getMonotonicUs();
|
||||
|
|
@ -3742,6 +3750,7 @@ void call(client *c, int flags) {
|
|||
else
|
||||
duration = ustime() - call_timer;
|
||||
|
||||
valkey_commands_trace(valkey_commands, command_call, connGetTypeId(c->conn), getClientPeerId(c), getClientPeerId(c), real_cmd->declared_name, duration);
|
||||
c->duration += duration;
|
||||
dirty = server.dirty - dirty;
|
||||
if (dirty < 0) dirty = 0;
|
||||
|
|
@ -3772,7 +3781,12 @@ void call(client *c, int flags) {
|
|||
* a MULTI-EXEC from inside an AOF). */
|
||||
if (update_command_stats) {
|
||||
char *latency_event = (real_cmd->flags & CMD_FAST) ? "fast-command" : "command";
|
||||
latencyAddSampleIfNeeded(latency_event, duration / 1000);
|
||||
latencyAddSampleIfNeeded(latency_event, duration);
|
||||
if (real_cmd->flags & CMD_FAST) {
|
||||
latencyTraceIfNeeded(server, fast_command, duration);
|
||||
} else {
|
||||
latencyTraceIfNeeded(server, command, duration);
|
||||
}
|
||||
if (server.execution_nesting == 0) durationAddSample(EL_DURATION_TYPE_CMD, duration);
|
||||
}
|
||||
|
||||
|
|
@ -6378,7 +6392,7 @@ void createPidFile(void) {
|
|||
void daemonize(void) {
|
||||
int fd;
|
||||
|
||||
if (fork() != 0) exit(0); /* parent exits */
|
||||
if (valkey_fork() != 0) exit(0); /* parent exits */
|
||||
setsid(); /* create a new session */
|
||||
|
||||
/* Every output goes to /dev/null. If the server is daemonized but
|
||||
|
|
@ -6572,7 +6586,7 @@ int serverFork(int purpose) {
|
|||
|
||||
int childpid;
|
||||
long long start = ustime();
|
||||
if ((childpid = fork()) == 0) {
|
||||
if ((childpid = valkey_fork()) == 0) {
|
||||
/* Child.
|
||||
*
|
||||
* The order of setting things up follows some reasoning:
|
||||
|
|
@ -6602,7 +6616,8 @@ int serverFork(int purpose) {
|
|||
server.stat_fork_time = ustime() - start;
|
||||
server.stat_fork_rate =
|
||||
(double)zmalloc_used_memory() * 1000000 / server.stat_fork_time / (1024 * 1024 * 1024); /* GB per second. */
|
||||
latencyAddSampleIfNeeded("fork", server.stat_fork_time / 1000);
|
||||
latencyAddSampleIfNeeded("fork", server.stat_fork_time);
|
||||
latencyTraceIfNeeded(bgsave, fork, server.stat_fork_time);
|
||||
|
||||
/* The child_pid and child_type are only for mutually exclusive children.
|
||||
* other child types should handle and store their pid's in dedicated variables.
|
||||
|
|
|
|||
11
src/server.h
11
src/server.h
|
|
@ -82,6 +82,13 @@ typedef long long ustime_t; /* microsecond time type. */
|
|||
#include "rax.h" /* Radix tree */
|
||||
#include "connection.h" /* Connection abstraction */
|
||||
#include "memory_prefetch.h"
|
||||
#include "trace/trace.h"
|
||||
|
||||
#ifdef USE_LTTNG
|
||||
#define valkey_fork() do_fork()
|
||||
#else
|
||||
#define valkey_fork() fork()
|
||||
#endif
|
||||
|
||||
#define dismissMemory zmadvise_dontneed
|
||||
|
||||
|
|
@ -137,10 +144,6 @@ struct hdr_histogram;
|
|||
#define CONFIG_DEFAULT_PID_FILE "/var/run/valkey.pid"
|
||||
#define CONFIG_DEFAULT_BINDADDR_COUNT 2
|
||||
#define CONFIG_DEFAULT_BINDADDR {"*", "-::*"}
|
||||
#define NET_HOST_STR_LEN 256 /* Longest valid hostname */
|
||||
#define NET_IP_STR_LEN 46 /* INET6_ADDRSTRLEN is 46, but we need to be sure */
|
||||
#define NET_ADDR_STR_LEN (NET_IP_STR_LEN + 32) /* Must be enough for ip:port */
|
||||
#define NET_HOST_PORT_STR_LEN (NET_HOST_STR_LEN + 32) /* Must be enough for hostname:port */
|
||||
#define CONFIG_BINDADDR_MAX 16
|
||||
#define CONFIG_MIN_RESERVED_FDS 32
|
||||
#define CONFIG_DEFAULT_PROC_TITLE_TEMPLATE "{title} {listen-addr} {server-mode}"
|
||||
|
|
|
|||
|
|
@ -53,6 +53,10 @@
|
|||
#define likely(x) (x)
|
||||
#endif
|
||||
|
||||
#ifdef assert
|
||||
#undef assert
|
||||
#endif
|
||||
|
||||
#define assert(_e) (likely((_e)) ? (void)0 : (_serverAssert(#_e, __FILE__, __LINE__), valkey_unreachable()))
|
||||
#define panic(...) _serverPanic(__FILE__, __LINE__, __VA_ARGS__), valkey_unreachable()
|
||||
|
||||
|
|
|
|||
|
|
@ -406,8 +406,15 @@ static const char *connSocketGetType(connection *conn) {
|
|||
return CONN_TYPE_SOCKET;
|
||||
}
|
||||
|
||||
static int connSocketGetTypeId(connection *conn) {
|
||||
(void)conn;
|
||||
|
||||
return CONN_TYPE_ID_SOCKET;
|
||||
}
|
||||
|
||||
static ConnectionType CT_Socket = {
|
||||
/* connection type */
|
||||
.get_type_id = connSocketGetTypeId,
|
||||
.get_type = connSocketGetType,
|
||||
|
||||
/* connection type initialize & finalize & configure */
|
||||
|
|
|
|||
|
|
@ -1120,6 +1120,12 @@ static const char *connTLSGetType(connection *conn_) {
|
|||
return CONN_TYPE_TLS;
|
||||
}
|
||||
|
||||
static int connTLSGetTypeId(connection *conn_) {
|
||||
(void)conn_;
|
||||
|
||||
return CONN_TYPE_ID_TLS;
|
||||
}
|
||||
|
||||
static int tlsHasPendingData(void) {
|
||||
if (!pending_list) return 0;
|
||||
return listLength(pending_list) > 0;
|
||||
|
|
@ -1166,6 +1172,7 @@ static sds connTLSGetPeerCert(connection *conn_) {
|
|||
|
||||
static ConnectionType CT_TLS = {
|
||||
/* connection type */
|
||||
.get_type_id = connTLSGetTypeId,
|
||||
.get_type = connTLSGetType,
|
||||
|
||||
/* connection type initialize & finalize & configure */
|
||||
|
|
|
|||
|
|
@ -0,0 +1,112 @@
|
|||
## Introduction
|
||||
|
||||
This directory contains the implementation of tracing using [LTTng](https://lttng.org/) (Linux Trace Toolkit Next Generation).
|
||||
|
||||
## LTTng Installation
|
||||
|
||||
To install LTTng on your Linux system, follow the instructions provided in the [LTTng documentation](https://lttng.org/download/)
|
||||
|
||||
> Dependency LTTNG version is greater than 2.12.
|
||||
|
||||
### Install from package manager
|
||||
|
||||
#### [Ubuntu](https://lttng.org/docs/v2.13/#doc-ubuntu)
|
||||
|
||||
LTTng 2.13 is available on Ubuntu 22.04 LTS *Jammy Jellyfish*, Ubuntu 23.04 *Lunar Lobster*, and Ubuntu 23.10 *Mantic Minotaur*. For previous supported releases of Ubuntu, [use the LTTng Stable 2.13 PPA](https://lttng.org/docs/v2.13/#doc-ubuntu-ppa).
|
||||
|
||||
To install LTTng 2.13 on Ubuntu 22.04 LTS *Jammy Jellyfish*:
|
||||
|
||||
1. Install the main LTTng 2.13 packages:
|
||||
|
||||
```
|
||||
apt-get install lttng-tools
|
||||
apt-get install lttng-modules-dkms
|
||||
apt-get install liblttng-ust-dev
|
||||
```
|
||||
|
||||
#### [Debian](https://lttng.org/docs/v2.13/#doc-debian)
|
||||
|
||||
To install LTTng 2.13 on Debian 12 *bookworm*:
|
||||
|
||||
1. Install the main LTTng 2.13 packages:
|
||||
```
|
||||
apt install lttng-modules-dkms
|
||||
apt install liblttng-ust-dev
|
||||
apt install lttng-tools
|
||||
```
|
||||
|
||||
## LTTng QuickStart
|
||||
|
||||
LTTng is an open source tracing framework for Linux that provides highly efficient and low-overhead tracing capabilities. It allows developers to trace both kernel and user-space applications.
|
||||
|
||||
Building Valkey with LTTng support:
|
||||
|
||||
```
|
||||
USE_LTTNG=yes make
|
||||
```
|
||||
|
||||
Enable lttng trace events dynamically:
|
||||
```
|
||||
~# lttng destroy valkey
|
||||
~# lttng create valkey
|
||||
~# lttng enable-event -u 'valkey_server:*'
|
||||
~# lttng track -u -p `pidof valkey-server`
|
||||
~# lttng start
|
||||
~# lttng stop
|
||||
~# lttng view
|
||||
```
|
||||
|
||||
Examples (a client run 'SET', another run 'keys'):
|
||||
```
|
||||
...
|
||||
[15:30:19.334467738] (+0.000001222) libai valkey:command_call: { cpu_id = 15 }, { name = "set", duration = 0 }
|
||||
[15:30:19.334469105] (+0.000001367) libai valkey:command_call: { cpu_id = 15 }, { name = "set", duration = 1 }
|
||||
[15:30:19.334470327] (+0.000001222) libai valkey:command_call: { cpu_id = 15 }, { name = "set", duration = 0 }
|
||||
[15:30:19.369348485] (+0.034878158) libai valkey:command_call: { cpu_id = 15 }, { name = "keys", duration = 34874 }
|
||||
[15:30:19.369698322] (+0.000349837) libai valkey:command_call: { cpu_id = 15 }, { name = "set", duration = 4 }
|
||||
[15:30:19.369702327] (+0.000004005) libai valkey:command_call: { cpu_id = 15 }, { name = "set", duration = 2 }
|
||||
[15:30:19.369704098] (+0.000001771) libai valkey:command_call: { cpu_id = 15 }, { name = "set", duration = 1 }
|
||||
[15:30:19.369705884] (+0.000001786) libai valkey:command_call: { cpu_id = 15 }, { name = "set", duration = 0 }
|
||||
...
|
||||
```
|
||||
|
||||
Then we can use another script to analyze topN slow commands and other system
|
||||
level events.
|
||||
|
||||
About performance overhead (valkey-benchmark -t get -n 1000000 --threads 4):
|
||||
1> no lttng builtin: 285632.69 requests per second
|
||||
2> lttng builtin, no trace: 285551.09 requests per second (almost 0 overhead)
|
||||
3> lttng builtin, trace commands: 266595.59 requests per second (about ~6.6 overhead)
|
||||
|
||||
Generally valkey-server would not run in full utilization, the overhead is acceptable.
|
||||
|
||||
## Supported Events
|
||||
|
||||
| event | provider |
|
||||
| -------------------------- | ----------------- |
|
||||
| command_call | valkey_commands |
|
||||
| rdb_unlink_temp_file | valkey_bgsave |
|
||||
| fork | valkey_bgsave |
|
||||
| while_blocked_cron | valkey_server |
|
||||
| module_acquire_gil | valkey_server |
|
||||
| command_unblocking | valkey_server |
|
||||
| expire_del | valkey_db |
|
||||
| active_defrag_cycle | valkey_db |
|
||||
| eviction_del | valkey_db |
|
||||
| eviction_lazyfree | valkey_db |
|
||||
| eviction_cycle | valkey_db |
|
||||
| expire_cycle | valkey_db |
|
||||
| cluster_config_open | valkey_cluster |
|
||||
| cluster_config_write | valkey_cluster |
|
||||
| cluster_config_fsync | valkey_cluster |
|
||||
| cluster_config_rename | valkey_cluster |
|
||||
| cluster_config_dir_fsync | valkey_cluster |
|
||||
| cluster_config_close | valkey_cluster |
|
||||
| cluster_config_unlink | valkey_cluster |
|
||||
| aof_write_pending_fsync | valkey_aof |
|
||||
| aof_write_active_child | valkey_aof |
|
||||
| aof_write_alone | valkey_aof |
|
||||
| aof_write | valkey_aof |
|
||||
| aof_fsync_always | valkey_aof |
|
||||
| aof_fstat | valkey_aof |
|
||||
| aof_rename | valkey_aof |
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) Valkey Contributors
|
||||
* All rights reserved.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
/* ==========================================================================
|
||||
* trace.c - support generic tracing layers.
|
||||
* --------------------------------------------------------------------------
|
||||
* Copyright (C) 2025 zhenwei pi <zhenwei.pi@linux.dev>
|
||||
* Copyright (C) 2025 zhiqiang li <lizhiqiang.sf@bytedance.com>
|
||||
*
|
||||
* This work is licensed under BSD 3-Clause, License 1 of the COPYING file in
|
||||
* the top-level directory.
|
||||
* ==========================================================================
|
||||
*/
|
||||
|
||||
#include "trace.h"
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef USE_LTTNG
|
||||
pid_t do_fork(void) {
|
||||
sigset_t sigset;
|
||||
int saved_errno;
|
||||
lttng_ust_before_fork(&sigset);
|
||||
int childpid = fork();
|
||||
saved_errno = errno;
|
||||
if (childpid != 0) {
|
||||
lttng_ust_after_fork_parent(&sigset);
|
||||
} else {
|
||||
lttng_ust_after_fork_child(&sigset);
|
||||
}
|
||||
errno = saved_errno;
|
||||
return childpid;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) Valkey Contributors
|
||||
* All rights reserved.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
/* ==========================================================================
|
||||
* trace.h - support generic tracing layers.
|
||||
* --------------------------------------------------------------------------
|
||||
* Copyright (C) 2025 zhenwei pi <zhenwei.pi@linux.dev>
|
||||
* Copyright (C) 2025 zhiqiang li <lizhiqiang.sf@bytedance.com>
|
||||
*
|
||||
* This work is licensed under BSD 3-Clause, License 1 of the COPYING file in
|
||||
* the top-level directory.
|
||||
* ==========================================================================
|
||||
*/
|
||||
|
||||
#if !defined(__VALKEY_TRACE_H__)
|
||||
#define __VALKEY_TRACE_H__
|
||||
|
||||
#include "trace_aof.h"
|
||||
#include "trace_cluster.h"
|
||||
#include "trace_server.h"
|
||||
#include "trace_db.h"
|
||||
#include "trace_bgsave.h"
|
||||
#include "trace_commands.h"
|
||||
|
||||
#ifdef USE_LTTNG
|
||||
#include <lttng/ust-fork.h>
|
||||
|
||||
#define LATENCY_TRACE_SWITCH 1
|
||||
pid_t do_fork(void);
|
||||
|
||||
#define latencyTraceIfNeeded(type, event, var) \
|
||||
valkey_##type##_trace(valkey_##type, event, (var));
|
||||
|
||||
#else
|
||||
|
||||
#define latencyTraceIfNeeded(type, event, var) \
|
||||
do { \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#endif /* __VALKEY_TRACE_H__ */
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright (c) Valkey Contributors
|
||||
* All rights reserved.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
/* ==========================================================================
|
||||
* trace_aof.c - support lttng tracing for aof events.
|
||||
* --------------------------------------------------------------------------
|
||||
* Copyright (C) 2025 zhenwei pi <zhenwei.pi@linux.dev>
|
||||
* Copyright (C) 2025 zhiqiang li <lizhiqiang.sf@bytedance.com>
|
||||
*
|
||||
* This work is licensed under BSD 3-Clause, License 1 of the COPYING file in
|
||||
* the top-level directory.
|
||||
* ==========================================================================
|
||||
*/
|
||||
|
||||
#define LTTNG_UST_TRACEPOINT_CREATE_PROBES
|
||||
#define LTTNG_UST_TRACEPOINT_DEFINE
|
||||
|
||||
#include "trace_aof.h"
|
||||
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Copyright (c) Valkey Contributors
|
||||
* All rights reserved.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
/* ==========================================================================
|
||||
* trace_aof.h - support lttng tracing for aof events.
|
||||
* --------------------------------------------------------------------------
|
||||
* Copyright (C) 2025 zhenwei pi <zhenwei.pi@linux.dev>
|
||||
* Copyright (C) 2025 zhiqiang li <lizhiqiang.sf@bytedance.com>
|
||||
*
|
||||
* This work is licensed under BSD 3-Clause, License 1 of the COPYING file in
|
||||
* the top-level directory.
|
||||
* ==========================================================================
|
||||
*/
|
||||
|
||||
#ifdef USE_LTTNG
|
||||
|
||||
#undef LTTNG_UST_TRACEPOINT_PROVIDER
|
||||
#define LTTNG_UST_TRACEPOINT_PROVIDER valkey_aof
|
||||
|
||||
#undef LTTNG_UST_TRACEPOINT_INCLUDE
|
||||
#define LTTNG_UST_TRACEPOINT_INCLUDE "./trace_aof.h"
|
||||
|
||||
#if !defined(__VALKEY_TRACE_AOF_H__) || defined(LTTNG_UST_TRACEPOINT_HEADER_MULTI_READ)
|
||||
#define __VALKEY_TRACE_AOF_H__
|
||||
|
||||
#include <lttng/tracepoint.h>
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_CLASS(
|
||||
/* Tracepoint class provider name */
|
||||
valkey_aof,
|
||||
|
||||
/* Tracepoint class name */
|
||||
valkey_aof_class,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
),
|
||||
|
||||
/* List of fields of eventual event (output) */
|
||||
LTTNG_UST_TP_FIELDS(
|
||||
lttng_ust_field_integer(uint64_t, duration, duration)
|
||||
)
|
||||
)
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_INSTANCE(
|
||||
/* Name of the tracepoint class provider */
|
||||
valkey_aof, valkey_aof_class, valkey_aof, aof_write_pending_fsync,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
)
|
||||
)
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_INSTANCE(
|
||||
/* Name of the tracepoint class provider */
|
||||
valkey_aof, valkey_aof_class, valkey_aof, aof_write_active_child,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
)
|
||||
)
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_INSTANCE(
|
||||
/* Name of the tracepoint class provider */
|
||||
valkey_aof, valkey_aof_class, valkey_aof, aof_write_alone,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
)
|
||||
)
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_INSTANCE(
|
||||
/* Name of the tracepoint class provider */
|
||||
valkey_aof, valkey_aof_class, valkey_aof, aof_write,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
)
|
||||
)
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_INSTANCE(
|
||||
/* Name of the tracepoint class provider */
|
||||
valkey_aof, valkey_aof_class, valkey_aof, aof_fsync_always,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
)
|
||||
)
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_INSTANCE(
|
||||
/* Name of the tracepoint class provider */
|
||||
valkey_aof, valkey_aof_class, valkey_aof, aof_fstat,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
)
|
||||
)
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_INSTANCE(
|
||||
/* Name of the tracepoint class provider */
|
||||
valkey_aof, valkey_aof_class, valkey_aof, aof_rename,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
)
|
||||
)
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_INSTANCE(
|
||||
/* Name of the tracepoint class provider */
|
||||
valkey_aof, valkey_aof_class, valkey_aof, aof_flush,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
)
|
||||
)
|
||||
|
||||
#define valkey_aof_trace(...) lttng_ust_tracepoint(__VA_ARGS__)
|
||||
|
||||
#endif /* __VALKEY_TRACE_AOF_H__ */
|
||||
|
||||
#include <lttng/tracepoint-event.h>
|
||||
|
||||
#else /* USE_LTTNG */
|
||||
|
||||
#ifndef __VALKEY_TRACE_AOF_H__
|
||||
#define __VALKEY_TRACE_AOF_H__
|
||||
|
||||
/* avoid compiler warning on empty source file */
|
||||
static inline void __valkey_aof_trace(void) {
|
||||
}
|
||||
|
||||
#define valkey_aof_trace(...) \
|
||||
do { \
|
||||
} while (0)
|
||||
|
||||
#endif /* __VALKEY_TRACE_AOF_H__ */
|
||||
|
||||
#endif /* USE_LTTNG */
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright (c) Valkey Contributors
|
||||
* All rights reserved.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
/* ==========================================================================
|
||||
* trace_sys.c - support lttng tracing for system events.
|
||||
* --------------------------------------------------------------------------
|
||||
* Copyright (C) 2025 zhenwei pi <zhenwei.pi@linux.dev>
|
||||
* Copyright (C) 2025 zhiqiang li <lizhiqiang.sf@bytedance.com>
|
||||
*
|
||||
* This work is licensed under BSD 3-Clause, License 1 of the COPYING file in
|
||||
* the top-level directory.
|
||||
* ==========================================================================
|
||||
*/
|
||||
|
||||
#define LTTNG_UST_TRACEPOINT_CREATE_PROBES
|
||||
#define LTTNG_UST_TRACEPOINT_DEFINE
|
||||
|
||||
#include "trace_bgsave.h"
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright (c) Valkey Contributors
|
||||
* All rights reserved.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
/* ==========================================================================
|
||||
* trace_bgsave.h - support lttng tracing for background Save.
|
||||
* --------------------------------------------------------------------------
|
||||
* Copyright (C) 2025 zhenwei pi <zhenwei.pi@linux.dev>
|
||||
* Copyright (C) 2025 zhiqiang li <lizhiqiang.sf@bytedance.com>
|
||||
*
|
||||
* This work is licensed under BSD 3-Clause, License 1 of the COPYING file in
|
||||
* the top-level directory.
|
||||
* ==========================================================================
|
||||
*/
|
||||
|
||||
#ifdef USE_LTTNG
|
||||
|
||||
#undef LTTNG_UST_TRACEPOINT_PROVIDER
|
||||
#define LTTNG_UST_TRACEPOINT_PROVIDER valkey_bgsave
|
||||
|
||||
#undef LTTNG_UST_TRACEPOINT_INCLUDE
|
||||
#define LTTNG_UST_TRACEPOINT_INCLUDE "./trace_bgsave.h"
|
||||
|
||||
#if !defined(__VALKEY_TRACE_SYS_H__) || defined(LTTNG_UST_TRACEPOINT_HEADER_MULTI_READ)
|
||||
#define __VALKEY_TRACE_SYS_H__
|
||||
|
||||
#include <lttng/tracepoint.h>
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_CLASS(
|
||||
/* Tracepoint class provider name */
|
||||
valkey_bgsave,
|
||||
|
||||
/* Tracepoint class name */
|
||||
valkey_bgsave_class,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
),
|
||||
|
||||
/* List of fields of eventual event (output) */
|
||||
LTTNG_UST_TP_FIELDS(
|
||||
lttng_ust_field_integer(uint64_t, duration, duration)
|
||||
)
|
||||
)
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_INSTANCE(
|
||||
/* Name of the tracepoint class provider */
|
||||
valkey_bgsave, valkey_bgsave_class, valkey_bgsave, fork,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
)
|
||||
)
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_INSTANCE(
|
||||
/* Name of the tracepoint class provider */
|
||||
valkey_bgsave, valkey_bgsave_class, valkey_bgsave, rdb_unlink_temp_file,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
)
|
||||
)
|
||||
|
||||
#define valkey_bgsave_trace(...) lttng_ust_tracepoint(__VA_ARGS__)
|
||||
|
||||
#endif /* __VALKEY_TRACE_SYS_H__ */
|
||||
|
||||
#include <lttng/tracepoint-event.h>
|
||||
|
||||
#else /* USE_LTTNG */
|
||||
|
||||
#ifndef __VALKEY_TRACE_SYS_H__
|
||||
#define __VALKEY_TRACE_SYS_H__
|
||||
|
||||
/* avoid compiler warning on empty source file */
|
||||
static inline void __valkey_bgsave_trace(void) {
|
||||
}
|
||||
|
||||
#define valkey_bgsave_trace(...) \
|
||||
do { \
|
||||
} while (0)
|
||||
|
||||
#endif /* __VALKEY_TRACE_SYS_H__ */
|
||||
|
||||
#endif /* USE_LTTNG */
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright (c) Valkey Contributors
|
||||
* All rights reserved.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
/* ==========================================================================
|
||||
* trace_cluster.c - support lttng tracing for cluster events.
|
||||
* --------------------------------------------------------------------------
|
||||
* Copyright (C) 2025 zhenwei pi <zhenwei.pi@linux.dev>
|
||||
* Copyright (C) 2025 zhiqiang li <lizhiqiang.sf@bytedance.com>
|
||||
*
|
||||
* This work is licensed under BSD 3-Clause, License 1 of the COPYING file in
|
||||
* the top-level directory.
|
||||
* ==========================================================================
|
||||
*/
|
||||
|
||||
#define LTTNG_UST_TRACEPOINT_CREATE_PROBES
|
||||
#define LTTNG_UST_TRACEPOINT_DEFINE
|
||||
|
||||
#include "trace_cluster.h"
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* Copyright (c) Valkey Contributors
|
||||
* All rights reserved.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
/* ==========================================================================
|
||||
* trace_cluster.h - support lttng tracing for cluster events.
|
||||
* --------------------------------------------------------------------------
|
||||
* Copyright (C) 2025 zhenwei pi <zhenwei.pi@linux.dev>
|
||||
* Copyright (C) 2025 zhiqiang li <lizhiqiang.sf@bytedance.com>
|
||||
*
|
||||
* This work is licensed under BSD 3-Clause, License 1 of the COPYING file in
|
||||
* the top-level directory.
|
||||
* ==========================================================================
|
||||
*/
|
||||
|
||||
#ifdef USE_LTTNG
|
||||
|
||||
#undef LTTNG_UST_TRACEPOINT_PROVIDER
|
||||
#define LTTNG_UST_TRACEPOINT_PROVIDER valkey_cluster
|
||||
|
||||
#undef LTTNG_UST_TRACEPOINT_INCLUDE
|
||||
#define LTTNG_UST_TRACEPOINT_INCLUDE "./trace_cluster.h"
|
||||
|
||||
#if !defined(__VALKEY_TRACE_CLUSTER_H__) || defined(LTTNG_UST_TRACEPOINT_HEADER_MULTI_READ)
|
||||
#define __VALKEY_TRACE_CLUSTER_H__
|
||||
|
||||
#include <lttng/tracepoint.h>
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_CLASS(
|
||||
/* Tracepoint class provider name */
|
||||
valkey_cluster,
|
||||
|
||||
/* Tracepoint class name */
|
||||
valkey_cluster_class,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
),
|
||||
|
||||
/* List of fields of eventual event (output) */
|
||||
LTTNG_UST_TP_FIELDS(
|
||||
lttng_ust_field_integer(uint64_t, duration, duration)
|
||||
)
|
||||
)
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_INSTANCE(
|
||||
/* Name of the tracepoint class provider */
|
||||
valkey_cluster, valkey_cluster_class, valkey_cluster, cluster_config_open,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
)
|
||||
)
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_INSTANCE(
|
||||
/* Name of the tracepoint class provider */
|
||||
valkey_cluster, valkey_cluster_class, valkey_cluster, cluster_config_write,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
)
|
||||
)
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_INSTANCE(
|
||||
/* Name of the tracepoint class provider */
|
||||
valkey_cluster, valkey_cluster_class, valkey_cluster, cluster_config_fsync,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
)
|
||||
)
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_INSTANCE(
|
||||
/* Name of the tracepoint class provider */
|
||||
valkey_cluster, valkey_cluster_class, valkey_cluster, cluster_config_rename,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
)
|
||||
)
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_INSTANCE(
|
||||
/* Name of the tracepoint class provider */
|
||||
valkey_cluster, valkey_cluster_class, valkey_cluster, cluster_config_dir_fsync,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
)
|
||||
)
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_INSTANCE(
|
||||
/* Name of the tracepoint class provider */
|
||||
valkey_cluster, valkey_cluster_class, valkey_cluster, cluster_config_close,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
)
|
||||
)
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_INSTANCE(
|
||||
/* Name of the tracepoint class provider */
|
||||
valkey_cluster, valkey_cluster_class, valkey_cluster, cluster_config_unlink,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
)
|
||||
)
|
||||
|
||||
#define valkey_cluster_trace(...) lttng_ust_tracepoint(__VA_ARGS__)
|
||||
|
||||
#endif /* __VALKEY_TRACE_CLUSTER_H__ */
|
||||
|
||||
#include <lttng/tracepoint-event.h>
|
||||
|
||||
#else /* USE_LTTNG */
|
||||
|
||||
#ifndef __VALKEY_TRACE_CLUSTER_H__
|
||||
#define __VALKEY_TRACE_CLUSTER_H__
|
||||
|
||||
/* avoid compiler warning on empty source file */
|
||||
static inline void __valkey_cluster_trace(void) {
|
||||
}
|
||||
|
||||
#define valkey_cluster_trace(...) \
|
||||
do { \
|
||||
} while (0)
|
||||
|
||||
#endif /* __VALKEY_TRACE_CLUSTER_H__ */
|
||||
|
||||
#endif /* USE_LTTNG */
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright (c) Valkey Contributors
|
||||
* All rights reserved.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
/* ==========================================================================
|
||||
* trace_commands.c - support lttng tracing for commands events.
|
||||
* --------------------------------------------------------------------------
|
||||
* Copyright (C) 2025 zhenwei pi <zhenwei.pi@linux.dev>
|
||||
* Copyright (C) 2025 zhiqiang li <lizhiqiang.sf@bytedance.com>
|
||||
*
|
||||
* This work is licensed under BSD 3-Clause, License 1 of the COPYING file in
|
||||
* the top-level directory.
|
||||
* ==========================================================================
|
||||
*/
|
||||
|
||||
#define LTTNG_UST_TRACEPOINT_CREATE_PROBES
|
||||
#define LTTNG_UST_TRACEPOINT_DEFINE
|
||||
|
||||
#include "trace_commands.h"
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright (c) Valkey Contributors
|
||||
* All rights reserved.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
/* ==========================================================================
|
||||
* trace_commands.h - support lttng tracing for commands events.
|
||||
* --------------------------------------------------------------------------
|
||||
* Copyright (C) 2025 zhenwei pi <zhenwei.pi@linux.dev>
|
||||
* Copyright (C) 2025 zhiqiang li <lizhiqiang.sf@bytedance.com>
|
||||
*
|
||||
* This work is licensed under BSD 3-Clause, License 1 of the COPYING file in
|
||||
* the top-level directory.
|
||||
* ==========================================================================
|
||||
*/
|
||||
|
||||
#ifdef USE_LTTNG
|
||||
|
||||
#undef LTTNG_UST_TRACEPOINT_PROVIDER
|
||||
#define LTTNG_UST_TRACEPOINT_PROVIDER valkey_commands
|
||||
|
||||
#undef LTTNG_UST_TRACEPOINT_INCLUDE
|
||||
#define LTTNG_UST_TRACEPOINT_INCLUDE "./trace_commands.h"
|
||||
|
||||
#if !defined(__VALKEY_TRACE_COMMANDS_H__) || defined(LTTNG_UST_TRACEPOINT_HEADER_MULTI_READ)
|
||||
#define __VALKEY_TRACE_COMMANDS_H__
|
||||
|
||||
#include <lttng/tracepoint.h>
|
||||
|
||||
LTTNG_UST_TRACEPOINT_ENUM(
|
||||
/* Tracepoint provider name */
|
||||
valkey_commands,
|
||||
|
||||
/* Tracepoint connection type enum */
|
||||
valkey_conn_type_enum,
|
||||
|
||||
/* Tracepoint connection type enum values, Source: ConnectionTypeId */
|
||||
LTTNG_UST_TP_ENUM_VALUES(
|
||||
lttng_ust_field_enum_value("SOCKET", 1)
|
||||
lttng_ust_field_enum_value("UNIX", 2)
|
||||
lttng_ust_field_enum_value("TLS", 3)
|
||||
lttng_ust_field_enum_value("RDMA", 4)
|
||||
)
|
||||
)
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT(
|
||||
/* Tracepoint provider name */
|
||||
valkey_commands,
|
||||
|
||||
/* Tracepoint name */
|
||||
command_call,
|
||||
|
||||
/* Input arguments */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
int, prot,
|
||||
const char *, saddr,
|
||||
const char *, daddr,
|
||||
const char *, name,
|
||||
uint64_t, duration
|
||||
),
|
||||
|
||||
/* Output event fields */
|
||||
LTTNG_UST_TP_FIELDS(
|
||||
lttng_ust_field_enum(valkey_commands, valkey_conn_type_enum, int, enum_field, prot)
|
||||
lttng_ust_field_string(saddr, saddr)
|
||||
lttng_ust_field_string(daddr, daddr)
|
||||
lttng_ust_field_string(name, name)
|
||||
lttng_ust_field_integer(uint64_t, duration, duration)
|
||||
)
|
||||
)
|
||||
|
||||
#define valkey_commands_trace(...) lttng_ust_tracepoint(__VA_ARGS__)
|
||||
|
||||
#endif /* __VALKEY_TRACE_COMMANDS_H__ */
|
||||
|
||||
#include <lttng/tracepoint-event.h>
|
||||
|
||||
#else /* USE_LTTNG */
|
||||
|
||||
#ifndef __VALKEY_TRACE_COMMANDS_H__
|
||||
#define __VALKEY_TRACE_COMMANDS_H__
|
||||
|
||||
/* avoid compiler warning on empty source file */
|
||||
static inline void __valkey_commands_trace(void) {
|
||||
}
|
||||
|
||||
#define valkey_commands_trace(...) \
|
||||
do { \
|
||||
} while (0)
|
||||
|
||||
#endif /* __VALKEY_TRACE_COMMANDS_H__ */
|
||||
|
||||
#endif /* USE_LTTNG */
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright (c) Valkey Contributors
|
||||
* All rights reserved.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
/* ==========================================================================
|
||||
* trace_db.c - support lttng tracing for db events.
|
||||
* --------------------------------------------------------------------------
|
||||
* Copyright (C) 2025 zhenwei pi <zhenwei.pi@linux.dev>
|
||||
* Copyright (C) 2025 zhiqiang li <lizhiqiang.sf@bytedance.com>
|
||||
*
|
||||
* This work is licensed under BSD 3-Clause, License 1 of the COPYING file in
|
||||
* the top-level directory.
|
||||
* ==========================================================================
|
||||
*/
|
||||
|
||||
#define LTTNG_UST_TRACEPOINT_CREATE_PROBES
|
||||
#define LTTNG_UST_TRACEPOINT_DEFINE
|
||||
|
||||
#include "trace_db.h"
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* Copyright (c) Valkey Contributors
|
||||
* All rights reserved.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
/* ==========================================================================
|
||||
* trace_db.h - support lttng tracing for db events.
|
||||
* --------------------------------------------------------------------------
|
||||
* Copyright (C) 2025 zhenwei pi <zhenwei.pi@linux.dev>
|
||||
* Copyright (C) 2025 zhiqiang li <lizhiqiang.sf@bytedance.com>
|
||||
*
|
||||
* This work is licensed under BSD 3-Clause, License 1 of the COPYING file in
|
||||
* the top-level directory.
|
||||
* ==========================================================================
|
||||
*/
|
||||
|
||||
#ifdef USE_LTTNG
|
||||
|
||||
#undef LTTNG_UST_TRACEPOINT_PROVIDER
|
||||
#define LTTNG_UST_TRACEPOINT_PROVIDER valkey_db
|
||||
|
||||
#undef LTTNG_UST_TRACEPOINT_INCLUDE
|
||||
#define LTTNG_UST_TRACEPOINT_INCLUDE "./trace_db.h"
|
||||
|
||||
#if !defined(__VALKEY_TRACE_DB_H__) || defined(LTTNG_UST_TRACEPOINT_HEADER_MULTI_READ)
|
||||
#define __VALKEY_TRACE_DB_H__
|
||||
|
||||
#include <lttng/tracepoint.h>
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_CLASS(
|
||||
/* Tracepoint class provider name */
|
||||
valkey_db,
|
||||
|
||||
/* Tracepoint class name */
|
||||
valkey_db_class,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
),
|
||||
|
||||
/* List of fields of eventual event (output) */
|
||||
LTTNG_UST_TP_FIELDS(
|
||||
lttng_ust_field_integer(uint64_t, duration, duration)
|
||||
)
|
||||
)
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_INSTANCE(
|
||||
/* Name of the tracepoint class provider */
|
||||
valkey_db, valkey_db_class, valkey_db, expire_del,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
)
|
||||
)
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_INSTANCE(
|
||||
/* Name of the tracepoint class provider */
|
||||
valkey_db, valkey_db_class, valkey_db, active_defrag_cycle,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
)
|
||||
)
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_INSTANCE(
|
||||
/* Name of the tracepoint class provider */
|
||||
valkey_db, valkey_db_class, valkey_db, eviction_del,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
)
|
||||
)
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_INSTANCE(
|
||||
/* Name of the tracepoint class provider */
|
||||
valkey_db, valkey_db_class, valkey_db, eviction_lazyfree,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
)
|
||||
)
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_INSTANCE(
|
||||
/* Name of the tracepoint class provider */
|
||||
valkey_db, valkey_db_class, valkey_db, eviction_cycle,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
)
|
||||
)
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_INSTANCE(
|
||||
/* Name of the tracepoint class provider */
|
||||
valkey_db, valkey_db_class, valkey_db, expire_cycle,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
)
|
||||
)
|
||||
|
||||
#define valkey_db_trace(...) lttng_ust_tracepoint(__VA_ARGS__)
|
||||
|
||||
#endif /* __VALKEY_TRACE_DB_H__ */
|
||||
|
||||
#include <lttng/tracepoint-event.h>
|
||||
|
||||
#else /* USE_LTTNG */
|
||||
|
||||
#ifndef __VALKEY_TRACE_DB_H__
|
||||
#define __VALKEY_TRACE_DB_H__
|
||||
|
||||
/* avoid compiler warning on empty source file */
|
||||
static inline void __valkey_db_trace(void) {
|
||||
}
|
||||
|
||||
#define valkey_db_trace(...) \
|
||||
do { \
|
||||
} while (0)
|
||||
|
||||
#endif /* __VALKEY_TRACE_DB_H__ */
|
||||
|
||||
#endif /* USE_LTTNG */
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright (c) Valkey Contributors
|
||||
* All rights reserved.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
/* ==========================================================================
|
||||
* trace_server.c - support lttng tracing for server events.
|
||||
* --------------------------------------------------------------------------
|
||||
* Copyright (C) 2025 zhenwei pi <zhenwei.pi@linux.dev>
|
||||
* Copyright (C) 2025 zhiqiang li <lizhiqiang.sf@bytedance.com>
|
||||
*
|
||||
* This work is licensed under BSD 3-Clause, License 1 of the COPYING file in
|
||||
* the top-level directory.
|
||||
* ==========================================================================
|
||||
*/
|
||||
|
||||
#define LTTNG_UST_TRACEPOINT_CREATE_PROBES
|
||||
#define LTTNG_UST_TRACEPOINT_DEFINE
|
||||
|
||||
#include "trace_server.h"
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* Copyright (c) Valkey Contributors
|
||||
* All rights reserved.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
/* ==========================================================================
|
||||
* trace_server.h - support lttng tracing for server events.
|
||||
* --------------------------------------------------------------------------
|
||||
* Copyright (C) 2025 zhenwei pi <zhenwei.pi@linux.dev>
|
||||
* Copyright (C) 2025 zhiqiang li <lizhiqiang.sf@bytedance.com>
|
||||
*
|
||||
* This work is licensed under BSD 3-Clause, License 1 of the COPYING file in
|
||||
* the top-level directory.
|
||||
* ==========================================================================
|
||||
*/
|
||||
|
||||
#ifdef USE_LTTNG
|
||||
|
||||
#undef LTTNG_UST_TRACEPOINT_PROVIDER
|
||||
#define LTTNG_UST_TRACEPOINT_PROVIDER valkey_server
|
||||
|
||||
#undef LTTNG_UST_TRACEPOINT_INCLUDE
|
||||
#define LTTNG_UST_TRACEPOINT_INCLUDE "./trace_server.h"
|
||||
|
||||
#if !defined(__VALKEY_TRACE_SERVER_H__) || defined(LTTNG_UST_TRACEPOINT_HEADER_MULTI_READ)
|
||||
#define __VALKEY_TRACE_SERVER_H__
|
||||
|
||||
#include <lttng/tracepoint.h>
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_CLASS(
|
||||
/* Tracepoint class provider name */
|
||||
valkey_server,
|
||||
|
||||
/* Tracepoint class name */
|
||||
valkey_server_class,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
),
|
||||
|
||||
/* List of fields of eventual event (output) */
|
||||
LTTNG_UST_TP_FIELDS(
|
||||
lttng_ust_field_integer(uint64_t, duration, duration)
|
||||
)
|
||||
)
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_INSTANCE(
|
||||
/* Name of the tracepoint class provider */
|
||||
valkey_server, valkey_server_class, valkey_server, command_unblocking,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
)
|
||||
)
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_INSTANCE(
|
||||
/* Name of the tracepoint class provider */
|
||||
valkey_server, valkey_server_class, valkey_server, while_blocked_cron,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
)
|
||||
)
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_INSTANCE(
|
||||
/* Name of the tracepoint class provider */
|
||||
valkey_server, valkey_server_class, valkey_server, eventloop,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
)
|
||||
)
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_INSTANCE(
|
||||
/* Name of the tracepoint class provider */
|
||||
valkey_server, valkey_server_class, valkey_server, eventloop_cron,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
)
|
||||
)
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_INSTANCE(
|
||||
/* Name of the tracepoint class provider */
|
||||
valkey_server, valkey_server_class, valkey_server, module_acquire_gil,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
)
|
||||
)
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_INSTANCE(
|
||||
/* Name of the tracepoint class provider */
|
||||
valkey_server, valkey_server_class, valkey_server, command,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
)
|
||||
)
|
||||
|
||||
LTTNG_UST_TRACEPOINT_EVENT_INSTANCE(
|
||||
/* Name of the tracepoint class provider */
|
||||
valkey_server, valkey_server_class, valkey_server, fast_command,
|
||||
|
||||
/* List of tracepoint arguments (input) */
|
||||
LTTNG_UST_TP_ARGS(
|
||||
uint64_t, duration
|
||||
)
|
||||
)
|
||||
|
||||
#define valkey_server_trace(...) lttng_ust_tracepoint(__VA_ARGS__)
|
||||
|
||||
#endif /* __VALKEY_TRACE_SERVER_H__ */
|
||||
|
||||
#include <lttng/tracepoint-event.h>
|
||||
|
||||
#else /* USE_LTTNG */
|
||||
|
||||
#ifndef __VALKEY_TRACE_SERVER_H__
|
||||
#define __VALKEY_TRACE_SERVER_H__
|
||||
|
||||
/* avoid compiler warning on empty source file */
|
||||
static inline void __valkey_server_trace(void) {
|
||||
}
|
||||
|
||||
#define valkey_server_trace(...) \
|
||||
do { \
|
||||
} while (0)
|
||||
|
||||
#endif /* __VALKEY_TRACE_SERVER_H__ */
|
||||
|
||||
#endif /* USE_LTTNG */
|
||||
|
|
@ -35,6 +35,12 @@ static const char *connUnixGetType(connection *conn) {
|
|||
return CONN_TYPE_UNIX;
|
||||
}
|
||||
|
||||
static int connUnixGetTypeId(connection *conn) {
|
||||
UNUSED(conn);
|
||||
|
||||
return CONN_TYPE_ID_UNIX;
|
||||
}
|
||||
|
||||
static void connUnixEventHandler(struct aeEventLoop *el, int fd, void *clientData, int mask) {
|
||||
connectionTypeTcp()->ae_handler(el, fd, clientData, mask);
|
||||
}
|
||||
|
|
@ -165,6 +171,7 @@ static ssize_t connUnixSyncReadLine(connection *conn, char *ptr, ssize_t size, l
|
|||
|
||||
static ConnectionType CT_Unix = {
|
||||
/* connection type */
|
||||
.get_type_id = connUnixGetTypeId,
|
||||
.get_type = connUnixGetType,
|
||||
|
||||
/* connection type initialize & finalize & configure */
|
||||
|
|
|
|||
Loading…
Reference in New Issue