Skip to content

Commit

Permalink
USDT Python API and example (#624)
Browse files Browse the repository at this point in the history
* Python USDT API

Code from @vmg

* Basic USDT example

* retire procstat.py

* improve/fix USDT exceptions
  • Loading branch information
brendangregg authored and 4ast committed Jul 23, 2016
1 parent f4bf275 commit 4f88a94
Show file tree
Hide file tree
Showing 10 changed files with 150 additions and 632 deletions.
54 changes: 54 additions & 0 deletions examples/tracing/nodejs_http_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#!/usr/bin/python
#
# nodejs_http_server Basic example of node.js USDT tracing.
# For Linux, uses BCC, BPF. Embedded C.
#
# USAGE: nodejs_http_server PID
#
# Copyright 2016 Netflix, Inc.
# Licensed under the Apache License, Version 2.0 (the "License")

from __future__ import print_function
from bcc import BPF, USDT
import sys

if len(sys.argv) < 2:
print("USAGE: nodejs_http_server PID")
exit()
pid = sys.argv[1]
debug = 0

# load BPF program
bpf_text = """
#include <uapi/linux/ptrace.h>
int do_trace(struct pt_regs *ctx) {
uint64_t addr;
char path[128];
bpf_usdt_readarg(6, ctx, &addr);
bpf_probe_read(&path, sizeof(path), (void *)addr);
bpf_trace_printk("path:%s\\n", path);
return 0;
};
"""

# enable USDT probe from given PID
u = USDT(pid=int(pid))
u.enable_probe(probe="http__server__request", fn_name="do_trace")
if debug:
print(u.get_text())
print(bpf_text)

# initialize BPF
b = BPF(text=bpf_text, usdt=u)

# header
print("%-18s %-16s %-6s %s" % ("TIME(s)", "COMM", "PID", "ARGS"))

# format output
while 1:
try:
(task, pid, cpu, flags, ts, msg) = b.trace_fields()
except ValueError:
print("value error")
continue
print("%-18.9f %-16s %-6d %s" % (ts, task, pid, msg))
2 changes: 1 addition & 1 deletion src/cc/bcc_usdt.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ void *bcc_usdt_new_frompath(const char *path);
void bcc_usdt_close(void *usdt);

int bcc_usdt_enable_probe(void *, const char *, const char *);
char *bcc_usdt_genargs(void *);
const char *bcc_usdt_genargs(void *);

typedef void (*bcc_usdt_uprobe_cb)(const char *, const char *, uint64_t, int);
void bcc_usdt_foreach_uprobe(void *usdt, bcc_usdt_uprobe_cb callback);
Expand Down
8 changes: 6 additions & 2 deletions src/cc/usdt.cc
Original file line number Diff line number Diff line change
Expand Up @@ -319,12 +319,16 @@ int bcc_usdt_enable_probe(void *usdt, const char *probe_name,
return ctx->enable_probe(probe_name, fn_name) ? 0 : -1;
}

char *bcc_usdt_genargs(void *usdt) {
const char *bcc_usdt_genargs(void *usdt) {
static std::string storage_;

USDT::Context *ctx = static_cast<USDT::Context *>(usdt);
std::ostringstream stream;
if (!ctx->generate_usdt_args(stream))
return nullptr;
return strdup(stream.str().c_str());

storage_ = stream.str();
return storage_.c_str();
}

void bcc_usdt_foreach_uprobe(void *usdt, bcc_usdt_uprobe_cb callback) {
Expand Down
7 changes: 1 addition & 6 deletions src/lua/bcc/usdt.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ See the License for the specific language governing permissions and
limitations under the License.
]]
local ffi = require("ffi")
ffi.cdef "void free(void *ptr);"

local libbcc = require("bcc.libbcc")
local Usdt = class("USDT")

Expand Down Expand Up @@ -56,10 +54,7 @@ end
function Usdt:_get_text()
local argc = libbcc.bcc_usdt_genargs(self.context)
assert(argc ~= nil)

local text = ffi.string(argc)
ffi.C.free(argc)
return text
return ffi.string(argc)
end

function Usdt:_attach_uprobes(bpf)
Expand Down
10 changes: 7 additions & 3 deletions src/python/bcc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
basestring = (unicode if sys.version_info[0] < 3 else str)

from .libbcc import lib, _CB_TYPE, bcc_symbol
from .procstat import ProcStat, ProcUtils
from .table import Table
from .tracepoint import Tracepoint
from .perf import Perf
Expand Down Expand Up @@ -117,7 +116,8 @@ def _find_file(filename):
raise Exception("Could not find file %s" % filename)
return filename

def __init__(self, src_file="", hdr_file="", text=None, cb=None, debug=0, cflags=[]):
def __init__(self, src_file="", hdr_file="", text=None, cb=None, debug=0,
cflags=[], usdt=None):
"""Create a a new BPF module with the given source code.
Note:
Expand Down Expand Up @@ -147,6 +147,8 @@ def __init__(self, src_file="", hdr_file="", text=None, cb=None, debug=0, cflags
self.tables = {}
cflags_array = (ct.c_char_p * len(cflags))()
for i, s in enumerate(cflags): cflags_array[i] = s.encode("ascii")
if usdt and text: text = usdt.get_text() + text

if text:
self.module = lib.bpf_module_create_c_from_string(text.encode("ascii"),
self.debug, cflags_array, len(cflags_array))
Expand All @@ -163,6 +165,8 @@ def __init__(self, src_file="", hdr_file="", text=None, cb=None, debug=0, cflags
if not self.module:
raise Exception("Failed to compile BPF module %s" % src_file)

if usdt: usdt.attach_uprobes(self)

# If any "kprobe__" or "tracepoint__" prefixed functions were defined,
# they will be loaded and attached here.
self._trace_autoload()
Expand Down Expand Up @@ -785,4 +789,4 @@ def cleanup(self):
self.tracefile.close()


from .usdt import USDTReader
from .usdt import USDT
20 changes: 20 additions & 0 deletions src/python/bcc/libbcc.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,23 @@ class bcc_symbol(ct.Structure):

lib.bcc_symcache_refresh.restype = None
lib.bcc_symcache_refresh.argtypes = [ct.c_void_p]

lib.bcc_usdt_new_frompid.restype = ct.c_void_p
lib.bcc_usdt_new_frompid.argtypes = [ct.c_int]

lib.bcc_usdt_new_frompath.restype = ct.c_void_p
lib.bcc_usdt_new_frompath.argtypes = [ct.c_char_p]

lib.bcc_usdt_close.restype = None
lib.bcc_usdt_close.argtypes = [ct.c_void_p]

lib.bcc_usdt_enable_probe.restype = ct.c_int
lib.bcc_usdt_enable_probe.argtypes = [ct.c_void_p, ct.c_char_p, ct.c_char_p]

lib.bcc_usdt_genargs.restype = ct.c_char_p
lib.bcc_usdt_genargs.argtypes = [ct.c_void_p]

_USDT_CB = ct.CFUNCTYPE(None, ct.c_char_p, ct.c_char_p, ct.c_ulonglong, ct.c_int)

lib.bcc_usdt_foreach_uprobe.restype = None
lib.bcc_usdt_foreach_uprobe.argtypes = [ct.c_void_p, _USDT_CB]
125 changes: 0 additions & 125 deletions src/python/bcc/procstat.py

This file was deleted.

Loading

0 comments on commit 4f88a94

Please sign in to comment.