Skip to content

Commit

Permalink
Merge pull request iovisor#3765 from bveldhoen/usdt_sample_update
Browse files Browse the repository at this point in the history
Updated usdt_sample for ubuntu 21.10 (and python3)
  • Loading branch information
davemarchevsky committed Dec 29, 2021
2 parents 13bac8d + d624578 commit 9adb763
Show file tree
Hide file tree
Showing 14 changed files with 738 additions and 249 deletions.
1 change: 1 addition & 0 deletions examples/usdt_sample/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
**/build*/
2 changes: 1 addition & 1 deletion examples/usdt_sample/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.0)
cmake_minimum_required(VERSION 3.12)

# This sample requires C++11 enabled.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Weffc++")
Expand Down
26 changes: 19 additions & 7 deletions examples/usdt_sample/scripts/bpf_text_shared.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,27 @@
/**
* @brief Helper method to filter based on the specified inputString.
* @param inputString The operation input string to check against the filter.
* @return True if the specified inputString starts with the hard-coded FILTER_STRING; otherwise, false.
* @return True if the specified inputString starts with the hard-coded filter string; otherwise, false.
*/
static inline bool filter(char const* inputString)
{
char needle[] = "FILTER_STRING"; ///< The FILTER STRING is replaced by python code.
char haystack[sizeof(needle)] = {};
bpf_probe_read_user(&haystack, sizeof(haystack), (void*)inputString);
for (int i = 0; i < sizeof(needle) - 1; ++i) {
if (needle[i] != haystack[i]) {
static const char* null_ptr = 0x0;
static const char null_terminator = '\0';

static const char filter_string[] = "FILTER_STRING"; ///< The filter string is replaced by python code.
if (null_ptr == inputString) {
return false;
}

// Compare until (not including) the null-terminator for filter_string
for (int i = 0; i < sizeof(filter_string) - 1; ++i) {
char c1 = *inputString++;
if (null_terminator == c1) {
return false; // If the null-terminator for inputString was reached, it can not be equal to filter_string.
}

char c2 = filter_string[i];
if (c1 != c2) {
return false;
}
}
Expand Down Expand Up @@ -45,7 +57,7 @@ int trace_operation_start(struct pt_regs* ctx)
struct start_data_t start_data = {};
bpf_usdt_readarg_p(2, ctx, &start_data.input, sizeof(start_data.input));

FILTER ///< Replaced by python code.
FILTER_STATEMENT ///< Replaced by python code.

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

Expand Down
52 changes: 29 additions & 23 deletions examples/usdt_sample/scripts/lat_avg.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,25 @@
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument("-p", "--pid", type=int, help="The id of the process to trace.")
parser.add_argument("-i", "--interval", type=int, help="The interval in seconds on which to report the latency distribution.")
parser.add_argument("-c", "--count", type=int, default=16, help="The count of samples over which to calculate the moving average.")
parser.add_argument("-c", "--count", type=int, default=16, help="The maximum number of samples over which to calculate the moving average.")
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.")
parser.add_argument("-v", "--verbose", dest="verbose", action="store_true", help="If true, will output verbose logging information.")
parser.add_argument("-v", "--verbose", dest="verbose", action="store_true", help="If true, will output generated bpf program and verbose logging information.")
parser.add_argument("-s", "--sdt", dest="sdt", action="store_true", help="If true, will use the probes, created by systemtap's dtrace.")

parser.set_defaults(verbose=False)
args = parser.parse_args()
this_pid = int(args.pid)
this_interval = int(args.interval)
this_count = int(args.count)
this_maxsamplesize = int(args.count)
this_filter = str(args.filterstr)

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

if this_count < 1:
print("Invalid value for count, using 1.")
this_count = 1
if this_maxsamplesize < 1:
print("Invalid value for this_maxsamplesize, using 1.")
this_maxsamplesize = 1

debugLevel=0
if args.verbose:
Expand All @@ -39,18 +41,18 @@
bpf_text = open(bpf_text_shared, 'r').read()
bpf_text += """
const u32 MAX_SAMPLES = SAMPLE_COUNT;
const u32 max_sample_size = MAX_SAMPLE_SIZE;
struct hash_key_t
{
char input[64];
char input[64]; // The operation id is used as key
};
struct hash_leaf_t
{
u32 count;
u64 total;
u64 average;
u32 sample_size; // Number of operation samples taken
u64 total; // Cumulative duration of the operations
u64 average; // Moving average duration of the operations
};
/**
Expand Down Expand Up @@ -83,45 +85,49 @@
return 0;
}
if (hash_leaf->count < MAX_SAMPLES) {
hash_leaf->count++;
if (hash_leaf->sample_size < max_sample_size) {
++hash_leaf->sample_size;
} else {
hash_leaf->total -= hash_leaf->average;
}
hash_leaf->total += duration;
hash_leaf->average = hash_leaf->total / hash_leaf->count;
hash_leaf->average = hash_leaf->total / hash_leaf->sample_size;
return 0;
}
"""

bpf_text = bpf_text.replace("SAMPLE_COUNT", str(this_count))
bpf_text = bpf_text.replace("MAX_SAMPLE_SIZE", str(this_maxsamplesize))
bpf_text = bpf_text.replace("FILTER_STRING", this_filter)
if this_filter:
bpf_text = bpf_text.replace("FILTER", "if (!filter(start_data.input)) { return 0; }")
bpf_text = bpf_text.replace("FILTER_STATEMENT", "if (!filter(start_data.input)) { return 0; }")
else:
bpf_text = bpf_text.replace("FILTER", "")
bpf_text = bpf_text.replace("FILTER_STATEMENT", "")

# Create USDT context
print("Attaching probes to pid %d" % this_pid)
print("lat_avg.py - Attaching probes to pid: %d; filter: %s" % (this_pid, this_filter))
usdt_ctx = USDT(pid=this_pid)
usdt_ctx.enable_probe(probe="operation_start", fn_name="trace_operation_start")
usdt_ctx.enable_probe(probe="operation_end", fn_name="trace_operation_end")

if args.sdt:
usdt_ctx.enable_probe(probe="usdt_sample_lib1_sdt:operation_start_sdt", fn_name="trace_operation_start")
usdt_ctx.enable_probe(probe="usdt_sample_lib1_sdt:operation_end_sdt", fn_name="trace_operation_end")
else:
usdt_ctx.enable_probe(probe="usdt_sample_lib1:operation_start", fn_name="trace_operation_start")
usdt_ctx.enable_probe(probe="usdt_sample_lib1:operation_end", fn_name="trace_operation_end")

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

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

lat_hash = bpf_ctx.get_table("lat_hash")
print("%-12s %-64s %8s %16s" % ("time", "input", "sample_size", "latency (us)"))
while (1):
try:
sleep(this_interval)
except KeyboardInterrupt:
exit()

print("[%s]" % strftime("%H:%M:%S"))
print("%-64s %8s %16s" % ("input", "count", "latency (us)"))
for k, v in lat_hash.items():
print("%-64s %8d %16d" % (k.input, v.count, v.average / 1000))
print("%-12s %-64s %8d %16d" % (strftime("%H:%M:%S"), k.input, v.sample_size, v.average / 1000))
23 changes: 16 additions & 7 deletions examples/usdt_sample/scripts/lat_dist.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
parser.add_argument("-p", "--pid", type=int, help="The id of the process to trace.")
parser.add_argument("-i", "--interval", type=int, help="The interval in seconds on which to report the latency distribution.")
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.")
parser.add_argument("-v", "--verbose", dest="verbose", action="store_true", help="If true, will output verbose logging information.")
parser.add_argument("-v", "--verbose", dest="verbose", action="store_true", help="If true, will output generated bpf program and verbose logging information.")
parser.add_argument("-s", "--sdt", dest="sdt", action="store_true", help="If true, will use the probes, created by systemtap's dtrace.")

parser.set_defaults(verbose=False)
args = parser.parse_args()
this_pid = int(args.pid)
Expand Down Expand Up @@ -67,26 +69,33 @@
dist_key.slot = bpf_log2l(duration / 1000);
start_hash.delete(&operation_id);
dist.increment(dist_key);
dist.atomic_increment(dist_key);
return 0;
}
"""

bpf_text = bpf_text.replace("FILTER_STRING", this_filter)
if this_filter:
bpf_text = bpf_text.replace("FILTER", "if (!filter(start_data.input)) { return 0; }")
bpf_text = bpf_text.replace("FILTER_STATEMENT", "if (!filter(start_data.input)) { return 0; }")
else:
bpf_text = bpf_text.replace("FILTER", "")
bpf_text = bpf_text.replace("FILTER_STATEMENT", "")

# Create USDT context
print("Attaching probes to pid %d" % this_pid)
print("lat_dist.py - Attaching probes to pid: %d; filter: %s" % (this_pid, this_filter))
usdt_ctx = USDT(pid=this_pid)
usdt_ctx.enable_probe(probe="operation_start", fn_name="trace_operation_start")
usdt_ctx.enable_probe(probe="operation_end", fn_name="trace_operation_end")

if args.sdt:
usdt_ctx.enable_probe(probe="usdt_sample_lib1_sdt:operation_start_sdt", fn_name="trace_operation_start")
usdt_ctx.enable_probe(probe="usdt_sample_lib1_sdt:operation_end_sdt", fn_name="trace_operation_end")
else:
usdt_ctx.enable_probe(probe="usdt_sample_lib1:operation_start", fn_name="trace_operation_start")
usdt_ctx.enable_probe(probe="usdt_sample_lib1:operation_end", fn_name="trace_operation_end")

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

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

start = 0
dist = bpf_ctx.get_table("dist")
while (1):
Expand Down
19 changes: 13 additions & 6 deletions examples/usdt_sample/scripts/latency.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument("-p", "--pid", type=int, help="The id of the process to trace.")
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.")
parser.add_argument("-v", "--verbose", dest="verbose", action="store_true", help="If true, will output verbose logging information.")
parser.add_argument("-v", "--verbose", dest="verbose", action="store_true", help="If true, will output generated bpf program and verbose logging information.")
parser.add_argument("-s", "--sdt", dest="sdt", action="store_true", help="If true, will use the probes, created by systemtap's dtrace.")

parser.set_defaults(verbose=False)
args = parser.parse_args()
this_pid = int(args.pid)
Expand Down Expand Up @@ -76,15 +78,20 @@

bpf_text = bpf_text.replace("FILTER_STRING", this_filter)
if this_filter:
bpf_text = bpf_text.replace("FILTER", "if (!filter(start_data.input)) { return 0; }")
bpf_text = bpf_text.replace("FILTER_STATEMENT", "if (!filter(start_data.input)) { return 0; }")
else:
bpf_text = bpf_text.replace("FILTER", "")
bpf_text = bpf_text.replace("FILTER_STATEMENT", "")

# Create USDT context
print("Attaching probes to pid %d" % this_pid)
print("latency.py - Attaching probes to pid: %d; filter: %s" % (this_pid, this_filter))
usdt_ctx = USDT(pid=this_pid)
usdt_ctx.enable_probe(probe="operation_start", fn_name="trace_operation_start")
usdt_ctx.enable_probe(probe="operation_end", fn_name="trace_operation_end")

if args.sdt:
usdt_ctx.enable_probe(probe="usdt_sample_lib1_sdt:operation_start_sdt", fn_name="trace_operation_start")
usdt_ctx.enable_probe(probe="usdt_sample_lib1_sdt:operation_end_sdt", fn_name="trace_operation_end")
else:
usdt_ctx.enable_probe(probe="usdt_sample_lib1:operation_start", fn_name="trace_operation_start")
usdt_ctx.enable_probe(probe="usdt_sample_lib1:operation_end", fn_name="trace_operation_end")

# Create BPF context, load BPF program
bpf_ctx = BPF(text=bpf_text, usdt_contexts=[usdt_ctx], debug=debugLevel)
Expand Down
Loading

0 comments on commit 9adb763

Please sign in to comment.