dftracer-annotate-python
Python annotation rules for dftracer — decorator usage, initialize/finalize, comp types, class methods, and quick checklist
SKILL.md.agents/skills/dftracer-annotate-python/SKILL.md
GitHubPython Annotation Rules (dftracer)
Python Rule 1 — Use the decorator for regular functions
from dftracer.logger import dftracer_fn, dft_fn
@dftracer_fn(cat="IO") # cat groups functions in the trace viewer
def my_read(path: str, size: int) -> bytes:
...
- The
@dftracer_fndecorator wraps the function with START/END automatically. cat(category) is required — use a meaningful group name:"IO","Compute","MPI","Data","Init", etc.dft_fnis an alias fordftracer_fn— preferdftracer_fnfor clarity.- Apply at every function that qualifies under Rule 0 (see dftracer-annotate-general skill).
Python Rule 2 — Initialize and finalize the tracer
from dftracer.logger import DFTracer
# At program entry (after MPI.Init if using mpi4py)
tracer = DFTracer.initialize_log(
log_file="traces/my_app", # prefix for .pfw trace files
data_dir="/data", # directory to monitor for I/O events
process_id=rank, # Pointer to MPI rank or 0 for single-process
)
# At program exit (before MPI.Finalize if using mpi4py)
DFTracer.finalize_log()
- With mpi4py: call
DFTracer.initialize_logAFTERMPI.Init(). - With mpi4py: call
DFTracer.finalize_log()BEFOREMPI.Finalize(). - Use
process_id=NULLfor single-process runs.
Python Rule 3 — Environment-variable initialization (alternative)
export DFTRACER_ENABLE=1
export DFTRACER_LOG_FILE=/tmp/traces/my_app
export DFTRACER_DATA_DIR=/data
python my_app.py
The env var only handles INIT/FINI — decorators are still needed for function-level spans.
Python Rule 4 — Context manager for ad-hoc regions
from dftracer.logger import DFTracer
tracer = DFTracer.get_instance()
with tracer.get_time("IO", "read_loop"):
for chunk in data:
process(chunk)
Only use context managers when the code block is too coarse-grained to fit a function decorator.
Python Rule 5 — Classify every annotated function with comp=TYPE
from dftracer.logger import dftracer_fn
@dftracer_fn(cat="IO", comp="io")
def read_checkpoint(path: str) -> dict: ...
@dftracer_fn(cat="COMM", comp="comm")
def broadcast_weights(tensor, comm): ...
@dftracer_fn(cat="CPU", comp="cpu")
def compute_checksum(data: bytes) -> str: ...
@dftracer_fn(cat="MEM", comp="mem")
def copy_batch(src, dst) -> None: ...
Types: "io", "mem", "cpu", "comm" — same taxonomy as C.
If dftracer_fn doesn't accept comp as a keyword argument:
@dftracer_fn(cat="IO")
def read_checkpoint(path: str) -> dict:
DFTracer.get_instance().update("comp", "io") # fallback
...
Python Rule 6 — Skip trivial functions (Rule 0 applies)
# ✅ Annotate — does real file I/O
@dftracer_fn(cat="IO")
def read_checkpoint(path: str, rank: int) -> dict:
with open(path, "rb") as f:
return pickle.load(f)
# ❌ Skip — trivial property
@property
def rank(self) -> int:
return self._rank
# ❌ Skip — one-liner string helper
def _fmt_path(self, p: str) -> str:
return str(Path(p).resolve())
Python Rule 7 — Class methods
class DataLoader:
@dftracer_fn(cat="IO")
def load(self, path: str, batch_size: int) -> list:
...
@dftracer_fn(cat="IO")
def write(self, path: str, data: bytes) -> None:
...
def _validate(self, x): # ❌ skip — trivial helper
return x is not None
Python Quick checklist
-
from dftracer.logger import dftracer_fnimported at top of file -
DFTracer.initialize_log(...)called at program entry (after MPI.Init if applicable) -
DFTracer.finalize_log()called at program exit (before MPI.Finalize if applicable) - ALL non-trivial functions decorated — skip only pure getters/one-liners
-
@dftracer_fn(cat="<CATEGORY>", comp="<type>")on every annotated function -
compis one of"io","mem","cpu","comm" - Category names are consistent across the codebase
- For mpi4py: initialize AFTER MPI.Init(), finalize BEFORE MPI.Finalize()