Skip to content

Commit 43f3ada

Browse files
committed
Merge bitcoin#19866: eBPF Linux tracepoints
22eb793 tracing: add tracing framework (William Casarin) 933ab8a build: detect sys/sdt.h for eBPF tracing (William Casarin) Pull request description: Instead of writing ad-hoc logging everywhere (eg: bitcoin#19509), we can take advantage of linux user static defined traces, aka. USDTs ( not the stablecoin 😅 ) The linux kernel can hook into these tracepoints at runtime, but otherwise they have little to no performance impact. Traces can pass data which can be printed externally via tools such as bpftrace. For example, here's one that prints incoming and outgoing network messages: # Examples ## Network Messages ``` #!/usr/bin/env bpftrace BEGIN { printf("bitcoin net msgs\n"); @start = nsecs; } usdt:./src/bitcoind:net:push_message { $ip = str(arg0); $peer_id = (int64)arg1; $command = str(arg2); $data_len = arg3; $data = buf(arg3,arg4); $t = (nsecs - @start) / 100000; printf("%zu outbound %s %s %zu %d %r\n", $t, $command, $ip, $peer_id, $data_len, $data); @outbound[$command]++; } usdt:./src/bitcoind:net:process_message { $ip = str(arg0); $peer_id = (int64)arg1; $command = str(arg2); $data_len = arg3; $data = buf(arg3,arg4); $t = (nsecs - @start) / 100000; printf("%zu inbound %s %s %zu %d %r\n", $t, $command, $ip, $peer_id, $data_len, $data); @inbound[$ip, $command]++; } ``` $ sudo bpftrace netmsg.bt output: https://jb55.com/s/b11312484b601fb3.txt if you look at the bottom of the output you can see a histogram of all the messages grouped by message type and IP. nice! ## IBD Benchmarking ``` #!/usr/bin/env bpftrace BEGIN { printf("IBD to 500,000 bench\n"); } usdt:./src/bitcoind:CChainState:ConnectBlock { $height = (uint32)arg0; if ($height == 1) { printf("block 1 found, starting benchmark\n"); @start = nsecs; } if ($height >= 500000) { @EnD = nsecs; @duration = @EnD - @start; exit(); } } END { printf("duration %d ms\n", @duration / 1000000) } ``` This one hooks into ConnectBlock and prints the IBD time to height 500,000 starting from the first call to ConnectBlock Userspace static tracepoints give lots of flexibility without invasive logging code. It's also more flexible than ad-hoc logging code, allowing you to instrument many different aspects of the system without having to enable per-subsystem logging. Other ideas: tracepoints for lock contention, threads, what else? Let me know what ya'll think and if this is worth adding to bitcoin. ## TODO - [ ] docs? - [x] Integrate systemtap-std-dev/libsystemtap into build (provides the <sys/sdt.h> header) - [x] ~dtrace macos support? (is this still a thing?)~ going to focus on linux for now ACKs for top commit: laanwj: Tested ACK 22eb793 0xB10C: Tested ACK 22eb793 Tree-SHA512: 69242242112b679c8a12a22b3bc50252c305894fb3055ae6e13d5f56221d858e58af1d698af55e23b69bdb7abedb5565ac6b45fa5144087b77a17acd04646a75
2 parents f7fd76b + 22eb793 commit 43f3ada

File tree

3 files changed

+64
-0
lines changed

3 files changed

+64
-0
lines changed

configure.ac

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,12 @@ AC_ARG_WITH([bdb],
132132
[use_bdb=$withval],
133133
[use_bdb=auto])
134134

135+
AC_ARG_ENABLE([ebpf],
136+
[AS_HELP_STRING([--enable-ebpf],
137+
[enable eBPF tracing (default is yes if sys/sdt.h is found)])],
138+
[use_ebpf=$enableval],
139+
[use_ebpf=yes])
140+
135141
AC_ARG_WITH([miniupnpc],
136142
[AS_HELP_STRING([--with-miniupnpc],
137143
[enable UPNP (default is yes if libminiupnpc is found)])],
@@ -1295,6 +1301,16 @@ if test x$enable_wallet != xno; then
12951301
fi
12961302
fi
12971303

1304+
if test x$use_ebpf != xno; then
1305+
AC_CHECK_HEADER([sys/sdt.h], [have_sdt=yes], [have_sdt=no])
1306+
else
1307+
have_sdt=no
1308+
fi
1309+
1310+
if test x$have_sdt = xyes; then
1311+
AC_DEFINE([ENABLE_TRACING], [1], [Define to 1 to enable eBPF user static defined tracepoints])
1312+
fi
1313+
12981314
dnl Check for libminiupnpc (optional)
12991315
if test x$use_upnp != xno; then
13001316
AC_CHECK_HEADERS(
@@ -1689,6 +1705,7 @@ AM_CONDITIONAL([TARGET_WINDOWS], [test x$TARGET_OS = xwindows])
16891705
AM_CONDITIONAL([ENABLE_WALLET],[test x$enable_wallet = xyes])
16901706
AM_CONDITIONAL([USE_SQLITE], [test "x$use_sqlite" = "xyes"])
16911707
AM_CONDITIONAL([USE_BDB], [test "x$use_bdb" = "xyes"])
1708+
AM_CONDITIONAL([ENABLE_TRACING],[test x$have_sdt = xyes])
16921709
AM_CONDITIONAL([ENABLE_TESTS],[test x$BUILD_TEST = xyes])
16931710
AM_CONDITIONAL([ENABLE_FUZZ],[test x$enable_fuzz = xyes])
16941711
AM_CONDITIONAL([ENABLE_FUZZ_LINK_ALL],[test x$enable_danger_fuzz_link_all = xyes])
@@ -1855,6 +1872,7 @@ echo " with bench = $use_bench"
18551872
echo " with upnp = $use_upnp"
18561873
echo " with natpmp = $use_natpmp"
18571874
echo " use asm = $use_asm"
1875+
echo " ebpf tracing = $have_sdt"
18581876
echo " sanitizers = $use_sanitizers"
18591877
echo " debug enabled = $enable_debug"
18601878
echo " gprof enabled = $enable_gprof"

src/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ BITCOIN_CORE_H = \
243243
util/system.h \
244244
util/threadnames.h \
245245
util/time.h \
246+
util/trace.h \
246247
util/translation.h \
247248
util/ui_change_type.h \
248249
util/url.h \

src/util/trace.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright (c) 2020 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#ifndef BITCOIN_UTIL_TRACE_H
6+
#define BITCOIN_UTIL_TRACE_H
7+
8+
#ifdef ENABLE_TRACING
9+
10+
#include <sys/sdt.h>
11+
12+
#define TRACE(context, event) DTRACE_PROBE(context, event)
13+
#define TRACE1(context, event, a) DTRACE_PROBE1(context, event, a)
14+
#define TRACE2(context, event, a, b) DTRACE_PROBE2(context, event, a, b)
15+
#define TRACE3(context, event, a, b, c) DTRACE_PROBE3(context, event, a, b, c)
16+
#define TRACE4(context, event, a, b, c, d) DTRACE_PROBE4(context, event, a, b, c, d)
17+
#define TRACE5(context, event, a, b, c, d, e) DTRACE_PROBE5(context, event, a, b, c, d, e)
18+
#define TRACE6(context, event, a, b, c, d, e, f) DTRACE_PROBE6(context, event, a, b, c, d, e, f)
19+
#define TRACE7(context, event, a, b, c, d, e, f, g) DTRACE_PROBE7(context, event, a, b, c, d, e, f, g)
20+
#define TRACE8(context, event, a, b, c, d, e, f, g, h) DTRACE_PROBE8(context, event, a, b, c, d, e, f, g, h)
21+
#define TRACE9(context, event, a, b, c, d, e, f, g, h, i) DTRACE_PROBE9(context, event, a, b, c, d, e, f, g, h, i)
22+
#define TRACE10(context, event, a, b, c, d, e, f, g, h, i, j) DTRACE_PROBE10(context, event, a, b, c, d, e, f, g, h, i, j)
23+
#define TRACE11(context, event, a, b, c, d, e, f, g, h, i, j, k) DTRACE_PROBE11(context, event, a, b, c, d, e, f, g, h, i, j, k)
24+
#define TRACE12(context, event, a, b, c, d, e, f, g, h, i, j, k, l) DTRACE_PROBE12(context, event, a, b, c, d, e, f, g, h, i, j, k, l)
25+
26+
#else
27+
28+
#define TRACE(context, event)
29+
#define TRACE1(context, event, a)
30+
#define TRACE2(context, event, a, b)
31+
#define TRACE3(context, event, a, b, c)
32+
#define TRACE4(context, event, a, b, c, d)
33+
#define TRACE5(context, event, a, b, c, d, e)
34+
#define TRACE6(context, event, a, b, c, d, e, f)
35+
#define TRACE7(context, event, a, b, c, d, e, f, g)
36+
#define TRACE8(context, event, a, b, c, d, e, f, g, h)
37+
#define TRACE9(context, event, a, b, c, d, e, f, g, h, i)
38+
#define TRACE10(context, event, a, b, c, d, e, f, g, h, i, j)
39+
#define TRACE11(context, event, a, b, c, d, e, f, g, h, i, j, k)
40+
#define TRACE12(context, event, a, b, c, d, e, f, g, h, i, j, k, l)
41+
42+
#endif
43+
44+
45+
#endif /* BITCOIN_UTIL_TRACE_H */

0 commit comments

Comments
 (0)