Skip to content

Commit 4f88a94

Browse files
brendangregg4ast
authored andcommitted
USDT Python API and example (#624)
* Python USDT API Code from @vmg * Basic USDT example * retire procstat.py * improve/fix USDT exceptions
1 parent f4bf275 commit 4f88a94

File tree

10 files changed

+150
-632
lines changed

10 files changed

+150
-632
lines changed
+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#!/usr/bin/python
2+
#
3+
# nodejs_http_server Basic example of node.js USDT tracing.
4+
# For Linux, uses BCC, BPF. Embedded C.
5+
#
6+
# USAGE: nodejs_http_server PID
7+
#
8+
# Copyright 2016 Netflix, Inc.
9+
# Licensed under the Apache License, Version 2.0 (the "License")
10+
11+
from __future__ import print_function
12+
from bcc import BPF, USDT
13+
import sys
14+
15+
if len(sys.argv) < 2:
16+
print("USAGE: nodejs_http_server PID")
17+
exit()
18+
pid = sys.argv[1]
19+
debug = 0
20+
21+
# load BPF program
22+
bpf_text = """
23+
#include <uapi/linux/ptrace.h>
24+
int do_trace(struct pt_regs *ctx) {
25+
uint64_t addr;
26+
char path[128];
27+
bpf_usdt_readarg(6, ctx, &addr);
28+
bpf_probe_read(&path, sizeof(path), (void *)addr);
29+
bpf_trace_printk("path:%s\\n", path);
30+
return 0;
31+
};
32+
"""
33+
34+
# enable USDT probe from given PID
35+
u = USDT(pid=int(pid))
36+
u.enable_probe(probe="http__server__request", fn_name="do_trace")
37+
if debug:
38+
print(u.get_text())
39+
print(bpf_text)
40+
41+
# initialize BPF
42+
b = BPF(text=bpf_text, usdt=u)
43+
44+
# header
45+
print("%-18s %-16s %-6s %s" % ("TIME(s)", "COMM", "PID", "ARGS"))
46+
47+
# format output
48+
while 1:
49+
try:
50+
(task, pid, cpu, flags, ts, msg) = b.trace_fields()
51+
except ValueError:
52+
print("value error")
53+
continue
54+
print("%-18.9f %-16s %-6d %s" % (ts, task, pid, msg))

src/cc/bcc_usdt.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ void *bcc_usdt_new_frompath(const char *path);
2727
void bcc_usdt_close(void *usdt);
2828

2929
int bcc_usdt_enable_probe(void *, const char *, const char *);
30-
char *bcc_usdt_genargs(void *);
30+
const char *bcc_usdt_genargs(void *);
3131

3232
typedef void (*bcc_usdt_uprobe_cb)(const char *, const char *, uint64_t, int);
3333
void bcc_usdt_foreach_uprobe(void *usdt, bcc_usdt_uprobe_cb callback);

src/cc/usdt.cc

+6-2
Original file line numberDiff line numberDiff line change
@@ -319,12 +319,16 @@ int bcc_usdt_enable_probe(void *usdt, const char *probe_name,
319319
return ctx->enable_probe(probe_name, fn_name) ? 0 : -1;
320320
}
321321

322-
char *bcc_usdt_genargs(void *usdt) {
322+
const char *bcc_usdt_genargs(void *usdt) {
323+
static std::string storage_;
324+
323325
USDT::Context *ctx = static_cast<USDT::Context *>(usdt);
324326
std::ostringstream stream;
325327
if (!ctx->generate_usdt_args(stream))
326328
return nullptr;
327-
return strdup(stream.str().c_str());
329+
330+
storage_ = stream.str();
331+
return storage_.c_str();
328332
}
329333

330334
void bcc_usdt_foreach_uprobe(void *usdt, bcc_usdt_uprobe_cb callback) {

src/lua/bcc/usdt.lua

+1-6
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
]]
1616
local ffi = require("ffi")
17-
ffi.cdef "void free(void *ptr);"
18-
1917
local libbcc = require("bcc.libbcc")
2018
local Usdt = class("USDT")
2119

@@ -56,10 +54,7 @@ end
5654
function Usdt:_get_text()
5755
local argc = libbcc.bcc_usdt_genargs(self.context)
5856
assert(argc ~= nil)
59-
60-
local text = ffi.string(argc)
61-
ffi.C.free(argc)
62-
return text
57+
return ffi.string(argc)
6358
end
6459

6560
function Usdt:_attach_uprobes(bpf)

src/python/bcc/__init__.py

+7-3
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
basestring = (unicode if sys.version_info[0] < 3 else str)
2626

2727
from .libbcc import lib, _CB_TYPE, bcc_symbol
28-
from .procstat import ProcStat, ProcUtils
2928
from .table import Table
3029
from .tracepoint import Tracepoint
3130
from .perf import Perf
@@ -117,7 +116,8 @@ def _find_file(filename):
117116
raise Exception("Could not find file %s" % filename)
118117
return filename
119118

120-
def __init__(self, src_file="", hdr_file="", text=None, cb=None, debug=0, cflags=[]):
119+
def __init__(self, src_file="", hdr_file="", text=None, cb=None, debug=0,
120+
cflags=[], usdt=None):
121121
"""Create a a new BPF module with the given source code.
122122
123123
Note:
@@ -147,6 +147,8 @@ def __init__(self, src_file="", hdr_file="", text=None, cb=None, debug=0, cflags
147147
self.tables = {}
148148
cflags_array = (ct.c_char_p * len(cflags))()
149149
for i, s in enumerate(cflags): cflags_array[i] = s.encode("ascii")
150+
if usdt and text: text = usdt.get_text() + text
151+
150152
if text:
151153
self.module = lib.bpf_module_create_c_from_string(text.encode("ascii"),
152154
self.debug, cflags_array, len(cflags_array))
@@ -163,6 +165,8 @@ def __init__(self, src_file="", hdr_file="", text=None, cb=None, debug=0, cflags
163165
if not self.module:
164166
raise Exception("Failed to compile BPF module %s" % src_file)
165167

168+
if usdt: usdt.attach_uprobes(self)
169+
166170
# If any "kprobe__" or "tracepoint__" prefixed functions were defined,
167171
# they will be loaded and attached here.
168172
self._trace_autoload()
@@ -785,4 +789,4 @@ def cleanup(self):
785789
self.tracefile.close()
786790

787791

788-
from .usdt import USDTReader
792+
from .usdt import USDT

src/python/bcc/libbcc.py

+20
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,23 @@ class bcc_symbol(ct.Structure):
135135

136136
lib.bcc_symcache_refresh.restype = None
137137
lib.bcc_symcache_refresh.argtypes = [ct.c_void_p]
138+
139+
lib.bcc_usdt_new_frompid.restype = ct.c_void_p
140+
lib.bcc_usdt_new_frompid.argtypes = [ct.c_int]
141+
142+
lib.bcc_usdt_new_frompath.restype = ct.c_void_p
143+
lib.bcc_usdt_new_frompath.argtypes = [ct.c_char_p]
144+
145+
lib.bcc_usdt_close.restype = None
146+
lib.bcc_usdt_close.argtypes = [ct.c_void_p]
147+
148+
lib.bcc_usdt_enable_probe.restype = ct.c_int
149+
lib.bcc_usdt_enable_probe.argtypes = [ct.c_void_p, ct.c_char_p, ct.c_char_p]
150+
151+
lib.bcc_usdt_genargs.restype = ct.c_char_p
152+
lib.bcc_usdt_genargs.argtypes = [ct.c_void_p]
153+
154+
_USDT_CB = ct.CFUNCTYPE(None, ct.c_char_p, ct.c_char_p, ct.c_ulonglong, ct.c_int)
155+
156+
lib.bcc_usdt_foreach_uprobe.restype = None
157+
lib.bcc_usdt_foreach_uprobe.argtypes = [ct.c_void_p, _USDT_CB]

src/python/bcc/procstat.py

-125
This file was deleted.

0 commit comments

Comments
 (0)