btetto 0.1.0

A tool that produces Perfetto protobuf from formatted bpftrace output.
btetto-0.1.0 is not a library.

btetto

A tool that produces Perfetto protobuf from formatted bpftrace output.

Usage

$ sudo bpftrace my_script.bt -f json | ./btetto
Attached probes: 4
^C
Writing 149 events to trace file: bpftrace_trace.binpb

btetto.py produces a bpftrace_trace.binpb protobuf file, which can then be loaded into the Perfetto UI.

bpftrace Output Format

The print output from bpftrace should be tuples (in JSON format e.g. -f json) where the first item in the tuple is the event type and the rest of the items are key/value tuples.

Event Types

  • track_event
  • track_descriptor
  • call_stack

Track Events (Spans)

These have three types: "BEGIN", "END", and "COUNTER" where "ts" is the timestamp of when these events occurred.

Required Fields:

  • name
  • ts
  • type

Optional Fields:

  • pid
  • thread_name
  • tid
  • track_name

If the field is not listed above it will get logged as an annotation on the event like "bananas" and "greeting" below.

print(("track_event", ("name", "page_fault_user"), ("type", "BEGIN"), ("ts", $start), ("pid", pid), ("tid", tid), ("thread_name", comm), ("bananas", 10), ("greeting", "hello")));
        
print(("track_event", ("name", "page_fault_user"), ("type", "END"), ("ts", nsecs), ("pid", pid), ("tid", tid), ("thread_name", comm)));

Track Descriptor

These define track names in the Perfetto UI. At the moment only "track_event" event types can utilize custom tracks and to do that they need to set the track name in your track event (above) e.g. (..., ("track_name", "Sub Parent A")).

There are three different types of descriptors:

  • name
  • thread_name
  • counter

name

These are generic descriptors and can specify a "parent".

print(("track_descriptor", ("name", "Top Parent")));
print(("track_descriptor", ("name", "Sub Parent A"), ("parent", "Top Parent")));

thread_name

These are specifically for naming pid/tid tracks and require both the "pid" and "tid" pairs. These will get added automatically if you have pid, tid, and thread_name in your track_event.

print(("track_descriptor", ("thread_name", comm), ("pid", pid), ("tid", tid)));

counter

These are for "COUNTER" type track events and require a "unit", which can be:

  • unspecified
  • count
  • size_bytes
  • time_ns
print(("track_descriptor", ("counter", "Donut Counts"), ("unit", "count")));

Call Stack Sample

These are for logging call stacks (kernel, user, or both) at specific points in time. They do not have durations.

Required Fields:

  • pid
  • tid
  • ts
  • kstack or ustack (or both)

Optional Fields:

  • thread_name
print(("call_stack", ("ts", nsecs), ("pid", pid), ("tid", tid), ("thread_name", comm), ("kstack", kstack), ("ustack", ustack)));