Reference

Configuration

One trace.config next to your code decides what gets hooks. It is read at every build, so changing it and rebuilding is the entire workflow.

Directives

One directive per line. # starts a comment; blank lines are ignored. With no directives at all, everything is instrumented.

DirectiveEffect
include <pattern> Only instrument matching sources. With no include line, every source is included.
exclude <pattern> Never instrument matching sources — or headers: the compiler matches the file a function is defined in, so a header path silences its inline/static helpers. Exclude always wins over include.
exclude-func <name> Never instrument functions whose (mangled) name contains <name> — the compiler's match is a substring match, so be specific.
include-func <name> [depth] Instrument <name> and its whole call subtree, resolved statically from your sources. Optional depth: 0 = just that function, 1 = direct callees, default = the full subtree.
counter <events> Hardware events to count, comma-separated — at most three. See hardware counters.
counter-func <name> [depth] Count <name>, and optionally its call subtree — the same walk include-func uses. Only instrumented functions can be counted.
counter-file <pattern> Count every instrumented function defined in matching files.
counter-min auto|<ns>|0 Skip counting functions shorter than this. auto (the default) derives it from the measured cost of one counter read; 0 disables the guard.
The first four directives decide what carries hooks, which is a compile-time decision and needs a rebuild to change. The counter ones decide what gets read from those hooks, which is resolved after the link and needs no rebuild at all — so you can re-point counters at different functions and just run again.

Pattern matching

A pattern matches a source path when it matches the full path or any trailing part of it — so src/utils/rng.c also matches ../project/src/utils/rng.c, whatever path your build passes to the compiler.

KindExamples
globsrc/net/** · *test*.c · rng.c
exact pathsrc/utils/rng.c
directory prefixsrc/sort · src/sort/

Three levels of selection

From coarsest to finest. The first two are compile-time and therefore free at runtime; the third is a runtime filter that needs no rebuild.

1 · File and folder

include / exclude patterns. The bluntest and cheapest instrument: whole translation units are compiled with or without hooks.

include src/network/
exclude src/network/crc.c

2 · Function and call subtree

include-func names an entry point — a task, a request handler, a workload — and callsight parses your sources, builds a static call graph, and instruments exactly the reachable subtree. Everything else defined in those files, including helpers defined in headers, is excluded by name at compile time.

$ callsight select src/ --function workload_sort
workload_sort: 31 functions across 6 files (full depth)
    heapsort
    mergesort
    qs_partition
    qs_swap
    …

# add to trace.config:
include-func workload_sort

Explore before committing: --depth 1 to see just the direct callees, --list to dump every function callsight can see.

Static resolution has limits. Calls through function pointers, macro-generated calls, and C++ dynamic dispatch are not followed — those callees simply don't get hooks. If a function you expected is missing from the report, that is the first thing to check.

3 · Thread

A runtime filter, matched against the thread name set with pthread_setname_np. No rebuild required.

$ TRACE_THREADS="sort-*,worker-1" TRACE_ENABLE=1 ./yourapp.instr

The name is checked at the thread's first hook call and re-checked periodically, since threads commonly set their name after starting. Expect a handful of unmatched_exits at activation for late-named threads — the events from before the thread matched are absent by design.

Strategy at scale

Event volume is the main cost. A call-heavy program easily generates millions of events per second, and the analyzer's job gets harder the more noise you feed it. The levers, cheapest first:

  1. Compile-time excludes. Run wide once, sort the report by calls, exclude the chatty leaf helpers, rebuild. Typically cuts volume 10–100× while keeping the structural picture intact.
  2. include directives. Instrument only the subsystem under investigation — include src/network/.
  3. include-func. One entry point, its exact call subtree, nothing else.
  4. Runtime gating. TRACE_ENABLE and TRACE_MAX control when and how much you pay; TRACE_THREADS narrows to the threads that matter.
  5. Source opt-out (the only one that touches your code): __attribute__((no_instrument_function)) on a single function.

Preview any config without building:

$ callsight scan src/ --config trace.config
35 sources: 34 instrumented, 1 excluded (config: trace.config)
  excluded: src/utils/rng.c

Runtime knobs

Environment variables read once, at the first hook call.

VariableDefaultMeaning
TRACE_ENABLEoff1 enables collection; hooks are inert otherwise
TRACE_DIR./tracesOutput directory (file mode)
TRACE_MAX0 (unlimited)Global event cap — always set one for long runs
TRACE_THREADSunset (all)Comma-separated globs on thread names, e.g. sort-*
TRACE_SHMunsetStreaming mode: POSIX shm ring name, e.g. /callsight0
TRACE_SHM_SIZE16 MiBRing capacity in bytes

A worked example

The selection used by the bundled matrixlab fixture — three lines that cut a noisy trace down to a readable one:

# trace.config
exclude src/utils/rng.c        # RNG helpers dominate call volume: pure noise
exclude src/signal/fft.h       # header-inline helpers defined in fft.h
exclude-func crc32_update     # one hot function, by name

# Exact instruction counts for the matrix work, and nothing too short
# to measure honestly.
counter instructions
counter-file src/matrix/**
counter-min auto

Which becomes, at build time:

-finstrument-functions
-finstrument-functions-exclude-file-list=src/utils/rng.c,src/signal/fft.h
-finstrument-functions-exclude-function-list=crc32_update
Prefer compile-time exclusion to anything else. An excluded function emits no hook: no call, no flag check, no branch. That is a guarantee no runtime filter can make.

Generate it by clicking

If you'd rather not write patterns by hand, the web UI's config builder enumerates every source file and function in the project and writes the config from your checkboxes — see the Web UI page.