Skip to content

fix: instrument library crates and impl methods in lib+bin projects#626

Merged
rocketman-code merged 5 commits intomainfrom
feat/example-target-clean
Apr 24, 2026
Merged

fix: instrument library crates and impl methods in lib+bin projects#626
rocketman-code merged 5 commits intomainfrom
feat/example-target-clean

Conversation

@rocketman-code
Copy link
Copy Markdown
Owner

Summary

  • Wrapper gate now passes library crates through to instrumentation when their module files contain measured functions (previously skipped because lib.rs has no functions itself, only mod declarations)
  • Rewriter constructs impl-qualified function names (e.g., Frame::check) matching the resolve module's format, so impl methods get guards injected
  • Integration test for the single-package lib+bin pattern (the most common Rust project structure)

Verified on mini-redis: all 33 active functions now report wall time, CPU time, call counts, and allocation data under realistic load (50 clients x 1000 ops).

Test Plan

  • New test single_package_lib_bin_instruments_library_functions passes
  • All existing workspace_layout tests pass (no regressions)
  • Full workspace suite green (0 failures)
  • Manual verification on mini-redis: library functions (Handler::run, Connection::read_frame, Db::set, Frame::parse) show non-zero calls and timing

Support cargo example targets via --example flag, mutually exclusive
with --bin. Generalize find_bin_target to find_target accepting a
target kind parameter. Update build_instrumented to accept CargoTarget
enum (Bin or Example). Extend find_latest_binary to scan the examples
subdirectory. Add unit test for example target discovery.
…ntation

Single-package projects with both [lib] and [[bin]] (the most common
Rust project structure) don't get library functions instrumented. The
wrapper gate at wrapper.rs:138 skips lib.rs because it has no measured
functions (only mod declarations), causing the entire library crate to
be passed through without instrumentation.

This test creates a lib+bin fixture and asserts that library functions
(compute::add, compute::multiply) record calls. It currently fails
with empty keys, proving the bug.
…jects

The wrapper gate (wrapper.rs:138) checked only whether the crate root
file was directly in config.targets or matched the entry point. For
lib+bin packages, lib.rs contains no functions (just mod declarations)
so it was absent from targets, causing the gate to skip the entire
library crate. All library functions went uninstrumented.

The fix adds a fallback: when the simple checks fail, check if any
target file starts_with(source_parent) of the crate root. This mirrors
the logic already used inside rewrite_and_compile (line 206) to
determine which files belong to a crate. Path::starts_with is
component-level, so no cross-package false positives are possible.
The rewriter looked up bare AST names (e.g., "check") in the measured
map, but the build pipeline stores impl-qualified names ("Frame::check").
Standalone functions matched (bare == qualified), but impl methods
never did -- their guards were silently never injected.

Add qualified_fn_name() that walks up the AST to find the enclosing
impl block and constructs the same qualified name that the resolve
module uses (via naming::render_impl_name). Both lookup sites in the
rewriter now use this function.

This is a hotfix using the same naming::render_impl_name as resolve.
The proper fix extracts a shared function so the name construction is
a single code path (MISU: make disagreement impossible, not improbable).
@rocketman-code rocketman-code merged commit 9d7bce0 into main Apr 24, 2026
11 checks passed
@rocketman-code rocketman-code deleted the feat/example-target-clean branch April 24, 2026 05:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant