Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 9adb763

Browse files
authoredDec 29, 2021
Merge pull request iovisor#3765 from bveldhoen/usdt_sample_update
Updated usdt_sample for ubuntu 21.10 (and python3)
2 parents 13bac8d + d624578 commit 9adb763

File tree

14 files changed

+738
-249
lines changed

14 files changed

+738
-249
lines changed
 

‎examples/usdt_sample/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
**/build*/

‎examples/usdt_sample/CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
cmake_minimum_required(VERSION 3.0)
1+
cmake_minimum_required(VERSION 3.12)
22

33
# This sample requires C++11 enabled.
44
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Weffc++")

‎examples/usdt_sample/scripts/bpf_text_shared.c

+19-7
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,27 @@
44
/**
55
* @brief Helper method to filter based on the specified inputString.
66
* @param inputString The operation input string to check against the filter.
7-
* @return True if the specified inputString starts with the hard-coded FILTER_STRING; otherwise, false.
7+
* @return True if the specified inputString starts with the hard-coded filter string; otherwise, false.
88
*/
99
static inline bool filter(char const* inputString)
1010
{
11-
char needle[] = "FILTER_STRING"; ///< The FILTER STRING is replaced by python code.
12-
char haystack[sizeof(needle)] = {};
13-
bpf_probe_read_user(&haystack, sizeof(haystack), (void*)inputString);
14-
for (int i = 0; i < sizeof(needle) - 1; ++i) {
15-
if (needle[i] != haystack[i]) {
11+
static const char* null_ptr = 0x0;
12+
static const char null_terminator = '\0';
13+
14+
static const char filter_string[] = "FILTER_STRING"; ///< The filter string is replaced by python code.
15+
if (null_ptr == inputString) {
16+
return false;
17+
}
18+
19+
// Compare until (not including) the null-terminator for filter_string
20+
for (int i = 0; i < sizeof(filter_string) - 1; ++i) {
21+
char c1 = *inputString++;
22+
if (null_terminator == c1) {
23+
return false; // If the null-terminator for inputString was reached, it can not be equal to filter_string.
24+
}
25+
26+
char c2 = filter_string[i];
27+
if (c1 != c2) {
1628
return false;
1729
}
1830
}
@@ -45,7 +57,7 @@ int trace_operation_start(struct pt_regs* ctx)
4557
struct start_data_t start_data = {};
4658
bpf_usdt_readarg_p(2, ctx, &start_data.input, sizeof(start_data.input));
4759

48-
FILTER ///< Replaced by python code.
60+
FILTER_STATEMENT ///< Replaced by python code.
4961

5062
bpf_usdt_readarg(1, ctx, &start_data.operation_id);
5163

‎examples/usdt_sample/scripts/lat_avg.py

+29-23
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,25 @@
1212
formatter_class=argparse.RawDescriptionHelpFormatter)
1313
parser.add_argument("-p", "--pid", type=int, help="The id of the process to trace.")
1414
parser.add_argument("-i", "--interval", type=int, help="The interval in seconds on which to report the latency distribution.")
15-
parser.add_argument("-c", "--count", type=int, default=16, help="The count of samples over which to calculate the moving average.")
15+
parser.add_argument("-c", "--count", type=int, default=16, help="The maximum number of samples over which to calculate the moving average.")
1616
parser.add_argument("-f", "--filterstr", type=str, default="", help="The prefix filter for the operation input. If specified, only operations for which the input string starts with the filterstr are traced.")
17-
parser.add_argument("-v", "--verbose", dest="verbose", action="store_true", help="If true, will output verbose logging information.")
17+
parser.add_argument("-v", "--verbose", dest="verbose", action="store_true", help="If true, will output generated bpf program and verbose logging information.")
18+
parser.add_argument("-s", "--sdt", dest="sdt", action="store_true", help="If true, will use the probes, created by systemtap's dtrace.")
19+
1820
parser.set_defaults(verbose=False)
1921
args = parser.parse_args()
2022
this_pid = int(args.pid)
2123
this_interval = int(args.interval)
22-
this_count = int(args.count)
24+
this_maxsamplesize = int(args.count)
2325
this_filter = str(args.filterstr)
2426

2527
if this_interval < 1:
2628
print("Invalid value for interval, using 1.")
2729
this_interval = 1
2830

29-
if this_count < 1:
30-
print("Invalid value for count, using 1.")
31-
this_count = 1
31+
if this_maxsamplesize < 1:
32+
print("Invalid value for this_maxsamplesize, using 1.")
33+
this_maxsamplesize = 1
3234

3335
debugLevel=0
3436
if args.verbose:
@@ -39,18 +41,18 @@
3941
bpf_text = open(bpf_text_shared, 'r').read()
4042
bpf_text += """
4143
42-
const u32 MAX_SAMPLES = SAMPLE_COUNT;
44+
const u32 max_sample_size = MAX_SAMPLE_SIZE;
4345
4446
struct hash_key_t
4547
{
46-
char input[64];
48+
char input[64]; // The operation id is used as key
4749
};
4850
4951
struct hash_leaf_t
5052
{
51-
u32 count;
52-
u64 total;
53-
u64 average;
53+
u32 sample_size; // Number of operation samples taken
54+
u64 total; // Cumulative duration of the operations
55+
u64 average; // Moving average duration of the operations
5456
};
5557
5658
/**
@@ -83,45 +85,49 @@
8385
return 0;
8486
}
8587
86-
if (hash_leaf->count < MAX_SAMPLES) {
87-
hash_leaf->count++;
88+
if (hash_leaf->sample_size < max_sample_size) {
89+
++hash_leaf->sample_size;
8890
} else {
8991
hash_leaf->total -= hash_leaf->average;
9092
}
9193
9294
hash_leaf->total += duration;
93-
hash_leaf->average = hash_leaf->total / hash_leaf->count;
95+
hash_leaf->average = hash_leaf->total / hash_leaf->sample_size;
9496
9597
return 0;
9698
}
9799
"""
98100

99-
bpf_text = bpf_text.replace("SAMPLE_COUNT", str(this_count))
101+
bpf_text = bpf_text.replace("MAX_SAMPLE_SIZE", str(this_maxsamplesize))
100102
bpf_text = bpf_text.replace("FILTER_STRING", this_filter)
101103
if this_filter:
102-
bpf_text = bpf_text.replace("FILTER", "if (!filter(start_data.input)) { return 0; }")
104+
bpf_text = bpf_text.replace("FILTER_STATEMENT", "if (!filter(start_data.input)) { return 0; }")
103105
else:
104-
bpf_text = bpf_text.replace("FILTER", "")
106+
bpf_text = bpf_text.replace("FILTER_STATEMENT", "")
105107

106108
# Create USDT context
107-
print("Attaching probes to pid %d" % this_pid)
109+
print("lat_avg.py - Attaching probes to pid: %d; filter: %s" % (this_pid, this_filter))
108110
usdt_ctx = USDT(pid=this_pid)
109-
usdt_ctx.enable_probe(probe="operation_start", fn_name="trace_operation_start")
110-
usdt_ctx.enable_probe(probe="operation_end", fn_name="trace_operation_end")
111+
112+
if args.sdt:
113+
usdt_ctx.enable_probe(probe="usdt_sample_lib1_sdt:operation_start_sdt", fn_name="trace_operation_start")
114+
usdt_ctx.enable_probe(probe="usdt_sample_lib1_sdt:operation_end_sdt", fn_name="trace_operation_end")
115+
else:
116+
usdt_ctx.enable_probe(probe="usdt_sample_lib1:operation_start", fn_name="trace_operation_start")
117+
usdt_ctx.enable_probe(probe="usdt_sample_lib1:operation_end", fn_name="trace_operation_end")
111118

112119
# Create BPF context, load BPF program
113120
bpf_ctx = BPF(text=bpf_text, usdt_contexts=[usdt_ctx], debug=debugLevel)
114121

115122
print("Tracing... Hit Ctrl-C to end.")
116123

117124
lat_hash = bpf_ctx.get_table("lat_hash")
125+
print("%-12s %-64s %8s %16s" % ("time", "input", "sample_size", "latency (us)"))
118126
while (1):
119127
try:
120128
sleep(this_interval)
121129
except KeyboardInterrupt:
122130
exit()
123131

124-
print("[%s]" % strftime("%H:%M:%S"))
125-
print("%-64s %8s %16s" % ("input", "count", "latency (us)"))
126132
for k, v in lat_hash.items():
127-
print("%-64s %8d %16d" % (k.input, v.count, v.average / 1000))
133+
print("%-12s %-64s %8d %16d" % (strftime("%H:%M:%S"), k.input, v.sample_size, v.average / 1000))

‎examples/usdt_sample/scripts/lat_dist.py

+16-7
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
parser.add_argument("-p", "--pid", type=int, help="The id of the process to trace.")
1414
parser.add_argument("-i", "--interval", type=int, help="The interval in seconds on which to report the latency distribution.")
1515
parser.add_argument("-f", "--filterstr", type=str, default="", help="The prefix filter for the operation input. If specified, only operations for which the input string starts with the filterstr are traced.")
16-
parser.add_argument("-v", "--verbose", dest="verbose", action="store_true", help="If true, will output verbose logging information.")
16+
parser.add_argument("-v", "--verbose", dest="verbose", action="store_true", help="If true, will output generated bpf program and verbose logging information.")
17+
parser.add_argument("-s", "--sdt", dest="sdt", action="store_true", help="If true, will use the probes, created by systemtap's dtrace.")
18+
1719
parser.set_defaults(verbose=False)
1820
args = parser.parse_args()
1921
this_pid = int(args.pid)
@@ -67,26 +69,33 @@
6769
dist_key.slot = bpf_log2l(duration / 1000);
6870
start_hash.delete(&operation_id);
6971
70-
dist.increment(dist_key);
72+
dist.atomic_increment(dist_key);
7173
return 0;
7274
}
7375
"""
7476

7577
bpf_text = bpf_text.replace("FILTER_STRING", this_filter)
7678
if this_filter:
77-
bpf_text = bpf_text.replace("FILTER", "if (!filter(start_data.input)) { return 0; }")
79+
bpf_text = bpf_text.replace("FILTER_STATEMENT", "if (!filter(start_data.input)) { return 0; }")
7880
else:
79-
bpf_text = bpf_text.replace("FILTER", "")
81+
bpf_text = bpf_text.replace("FILTER_STATEMENT", "")
8082

8183
# Create USDT context
82-
print("Attaching probes to pid %d" % this_pid)
84+
print("lat_dist.py - Attaching probes to pid: %d; filter: %s" % (this_pid, this_filter))
8385
usdt_ctx = USDT(pid=this_pid)
84-
usdt_ctx.enable_probe(probe="operation_start", fn_name="trace_operation_start")
85-
usdt_ctx.enable_probe(probe="operation_end", fn_name="trace_operation_end")
86+
87+
if args.sdt:
88+
usdt_ctx.enable_probe(probe="usdt_sample_lib1_sdt:operation_start_sdt", fn_name="trace_operation_start")
89+
usdt_ctx.enable_probe(probe="usdt_sample_lib1_sdt:operation_end_sdt", fn_name="trace_operation_end")
90+
else:
91+
usdt_ctx.enable_probe(probe="usdt_sample_lib1:operation_start", fn_name="trace_operation_start")
92+
usdt_ctx.enable_probe(probe="usdt_sample_lib1:operation_end", fn_name="trace_operation_end")
8693

8794
# Create BPF context, load BPF program
8895
bpf_ctx = BPF(text=bpf_text, usdt_contexts=[usdt_ctx], debug=debugLevel)
8996

97+
print("Tracing... Hit Ctrl-C to end.")
98+
9099
start = 0
91100
dist = bpf_ctx.get_table("dist")
92101
while (1):

‎examples/usdt_sample/scripts/latency.py

+13-6
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
formatter_class=argparse.RawDescriptionHelpFormatter)
1313
parser.add_argument("-p", "--pid", type=int, help="The id of the process to trace.")
1414
parser.add_argument("-f", "--filterstr", type=str, default="", help="The prefix filter for the operation input. If specified, only operations for which the input string starts with the filterstr are traced.")
15-
parser.add_argument("-v", "--verbose", dest="verbose", action="store_true", help="If true, will output verbose logging information.")
15+
parser.add_argument("-v", "--verbose", dest="verbose", action="store_true", help="If true, will output generated bpf program and verbose logging information.")
16+
parser.add_argument("-s", "--sdt", dest="sdt", action="store_true", help="If true, will use the probes, created by systemtap's dtrace.")
17+
1618
parser.set_defaults(verbose=False)
1719
args = parser.parse_args()
1820
this_pid = int(args.pid)
@@ -76,15 +78,20 @@
7678

7779
bpf_text = bpf_text.replace("FILTER_STRING", this_filter)
7880
if this_filter:
79-
bpf_text = bpf_text.replace("FILTER", "if (!filter(start_data.input)) { return 0; }")
81+
bpf_text = bpf_text.replace("FILTER_STATEMENT", "if (!filter(start_data.input)) { return 0; }")
8082
else:
81-
bpf_text = bpf_text.replace("FILTER", "")
83+
bpf_text = bpf_text.replace("FILTER_STATEMENT", "")
8284

8385
# Create USDT context
84-
print("Attaching probes to pid %d" % this_pid)
86+
print("latency.py - Attaching probes to pid: %d; filter: %s" % (this_pid, this_filter))
8587
usdt_ctx = USDT(pid=this_pid)
86-
usdt_ctx.enable_probe(probe="operation_start", fn_name="trace_operation_start")
87-
usdt_ctx.enable_probe(probe="operation_end", fn_name="trace_operation_end")
88+
89+
if args.sdt:
90+
usdt_ctx.enable_probe(probe="usdt_sample_lib1_sdt:operation_start_sdt", fn_name="trace_operation_start")
91+
usdt_ctx.enable_probe(probe="usdt_sample_lib1_sdt:operation_end_sdt", fn_name="trace_operation_end")
92+
else:
93+
usdt_ctx.enable_probe(probe="usdt_sample_lib1:operation_start", fn_name="trace_operation_start")
94+
usdt_ctx.enable_probe(probe="usdt_sample_lib1:operation_end", fn_name="trace_operation_end")
8895

8996
# Create BPF context, load BPF program
9097
bpf_ctx = BPF(text=bpf_text, usdt_contexts=[usdt_ctx], debug=debugLevel)
There was a problem loading the remainder of the diff.

0 commit comments

Comments
 (0)
Please sign in to comment.