CLI
| Command | Purpose |
|---|---|
callsight init <dir> | Adopt callsight into a project: copy the runtime and build wiring, write a starter config, print the wiring snippet |
callsight scan <dir> | Preview which sources a config selects, without building |
callsight select <dir> | Explore a function's call subtree; emit the matching config lines |
callsight flags | Print the compiler flags (what the build integrations call) |
callsight analyze [traces/] | Hotspot report, JSON, or folded stacks |
callsight ui | Local web UI (needs the ui extra) |
callsight serve | TCP server for remote streams (needs the stream extra) |
callsight provision | Download the bundled static ctags used by the UI config builder |
callsight --version | Installed version |
init
callsight init <dir> [--build make|cmake] [--stream]
--build | Force the build system. Default: auto-detect (CMakeLists.txt → cmake, else make) |
--stream | Also copy the on-device streaming client (trace_stream.c + vendored zstd) |
An existing trace.config is never overwritten.
scan
callsight scan <dir> [--config trace.config]
Prints how many sources would be instrumented versus excluded, lists the excluded ones,
and — for an include-func config — the subtree size and any
substring-collision warnings.
select
callsight select <dir> --function NAME [--depth N] [--threads GLOB] [--list]
--function, -f | Seed function; repeatable |
--depth, -d | Limit subtree expansion (0 = just the seed, 1 = direct callees). Default: full subtree |
--threads, -t | Also print a TRACE_THREADS runtime hint |
--list, -l | List every function callsight can see, with the files defining it |
flags
callsight flags --config CONFIG [--scan DIR] [--format make|raw]
[--compiler auto|gcc|clang] [--compiler-cmd CC] [--print] -- srcs...
--config | Config path (required) |
--scan DIR | Collect sources recursively under DIR instead of listing them |
--format | make (default) prints a CFLAGS_INSTRUMENT = … assignment for $(eval $(shell …)); raw prints only the flags |
--compiler | Target toolchain. auto (default) detects it by running --compiler-cmd |
--compiler-cmd | Compiler command used for detection. Default: $CC, else cc |
--print | Human-readable selection summary on stderr |
A selective config under a detected Clang exits with an explanation rather than emitting GCC-only flags. A failed detection is treated as GCC, so detection can never break a build that would otherwise work.
analyze
callsight analyze [tracedir] [--exe BIN] [--top N] [--format text|json|folded]
tracedir | Directory of trace.*.bin files. Default traces |
--exe | Instrumented binary for addr2line. Default: the single *.instr under ./bin or . |
--top | Rows per table (default 20). With --format json, 0 means every row |
--format | text tables (default), json for tooling, or folded collapsed stacks for flamegraph.pl and speedscope |
serve · ui · provision
callsight serve [--host 0.0.0.0] [--port 9001] [--out traces]
callsight ui [--host 127.0.0.1] [--port 8321]
callsight provision [--force]
provision reports where ctags comes from and installs the bundled static
copy into $CALLSIGHT_HOME/bin (default ~/.callsight/bin),
verifying its checksum. --force installs it even when a system ctags is
present.
Build integrations
Both do the same three things: generate the flags from your config and source list,
compile the runtime without instrumentation so hooks cannot recurse, and
link with -no-pie.
GNU Make
CALLSIGHT_DIR ?= callsight
include $(CALLSIGHT_DIR)/Makefile.callsight
Expects SRCS, BUILDDIR, BINDIR,
TARGET, CC, CFLAGS_SYMBOLS and LDFLAGS.
Defines:
CFLAGS_INSTRUMENT— yourCFLAGS_SYMBOLSplus hooks plus the exclude listsTRACE_OBJ— the runtime object, built without instrumentation
| Variable | Default | Meaning |
|---|---|---|
CALLSIGHT_DIR | callsight | Where trace.c/trace.h live |
CALLSIGHT_CONFIG | trace.config | Selection config |
CALLSIGHT | callsight | Command that prints the flags — point it at python3 …/cli.py to run from a source checkout |
When make instrument is requested and no flags could be generated, the
build stops with an explanation instead of silently producing an uninstrumented binary. A
normal make still succeeds even if callsight isn't installed.
CMake
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/callsight")
include(CallSight)
callsight_instrument(<target>)
| Cache variable | Default | Meaning |
|---|---|---|
CALLSIGHT_INSTRUMENT | OFF | Apply hooks to callsight_instrument() targets |
CALLSIGHT_CONFIG | <src>/trace.config | Selection config |
CALLSIGHT_COMMAND | callsight | Flag generator; a ;-list works, e.g. -D"CALLSIGHT_COMMAND=python3;/path/cli.py" |
CALLSIGHT_COMMAND is a cache variable — pass it with
-D. A plain set() before include(CallSight) gets
shadowed by the cache definition under CMP0126.
Environment variables
| Variable | Default | Meaning |
|---|---|---|
TRACE_ENABLE | off | 1 enables collection; hooks are inert otherwise |
TRACE_DIR | ./traces | Output directory (file mode) |
TRACE_MAX | 0 (unlimited) | Global event cap |
TRACE_THREADS | unset (all) | Comma-separated globs matched against thread names |
TRACE_SHM | unset | Streaming mode: POSIX shm ring name |
TRACE_SHM_SIZE | 16 MiB | Ring capacity in bytes |
CC | cc | Read by callsight flags for compiler detection |
CALLSIGHT_HOME | ~/.callsight | Where the bundled ctags is installed |
File formats
Trace files
trace.<pid>.<tid>.bin (file mode) or
trace.stream.<id>.bin (streamed). A 16-byte header —
MLTRACE magic, u32 version, u32 event size —
followed by fixed 32-byte little-endian event records. The
architecture page documents the record; a file with a
bad magic, unknown version or mismatched event size is skipped with a warning, and a
truncated final record is tolerated.
Folded stacks
main;handle_request;parse_headers 148230
main;handle_request 92117
One line per distinct call path: semicolon-separated frames, then self time in nanoseconds. Read directly by flamegraph.pl and speedscope.
JSON report
Summary counters (events, threads, functions,
span_ms, unmatched_exits, unclosed_enters), a
rows array sorted by self time, a per_thread array, plus
tool and version. See the
analysis page for a full example.
Known limitations
- Selective instrumentation is GCC-only. Clang has
-finstrument-functionsbut not the exclude lists (LLVM #15627); under Clang only an unfiltered config builds. - Linux only. The runtime uses
SYS_gettid,pthread_getname_npand POSIX shared memory. - Inlined functions emit no hooks — there is no call boundary to hook.
- Overhead is ~30–60 ns per event. This is a profiling build, not a production one.
- A crashed or killed process loses each thread's buffered tail. Clean exits flush everything.
- The compiler's exclude matching is substring-based, so unusually
overlapping directory or symbol names can over-match. callsight guards the
auto-generated function excludes against this and warns, but hand-written
exclude-funcentries are yours to keep specific. - Analysis needs
-no-pieso recorded addresses match link addresses. Both integrations do this;analyzewarns when most addresses fail to resolve. - Static call-graph resolution does not follow function pointers, macro-generated calls, or C++ dynamic dispatch.