tracing-tracy

A tracing-subscriber Layer that streams Rust application spans and events straight into the Tracy profiler.

Library
Cargo
v0.12.0
328stars
MIT OR Apache-2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
59/100Fair
Development Activity64
Maintenance20
Community72
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
76/100Good
Architecture80
Code Quality78
Innovation75
Learning Curve70

tracing-tracy bridges Rust’s tracing ecosystem with Tracy, a mature C++ profiler offering nanosecond-precision, remotely-viewable traces through a full graphical interface. If an application is already instrumented with tracing spans and events, adding tracing_tracy::TracyLayer to the subscriber stack is usually enough to get useful, real-time profiling data flowing into the Tracy GUI in minutes, without touching any instrumentation call sites.

The crate is one part of a three-crate workspace maintained by the same author: tracing-tracy (the tracing integration), tracy-client (a safe Rust wrapper around Tracy’s client protocol), and tracy-client-sys (raw FFI bindings that compile a vendored copy of the Tracy C++ client at build time). Because Tracy’s client can broadcast discovery packets and expose collected data on the local network, the crate exposes most of Tracy’s compile-time capture options — system tracing, context-switch tracing, call-stack sampling, code transfer, crash-handler capture — as granular, individually toggleable Cargo features so teams can scope exactly what a build collects.

What You Get

  • TracyLayer - a drop-in tracing_subscriber::Layer that can be composed onto any existing tracing subscriber registry with one line.
  • Automatic span-to-zone mapping - active tracing spans on each thread are tracked on a thread-local stack and reported to Tracy as profiling zones with source location, matching Tracy’s native zone model.
  • Configurable formatting via the Config trait - DefaultConfig or a custom implementation controls how span fields and event messages are rendered into Tracy’s message stream, plus stack-depth and truncation behavior.
  • Granular capture features - broadcast, system-tracing, context-switch-tracing, sampling, code-transfer, callstack-inlines, crash-handler, wait-stacks, ondemand, and more, each mapped 1:1 to a Tracy compile-time define so builds only compile in the capture paths they need.
  • Re-exported tracy-client - the underlying tracy-client crate (and its Client/Span types) is re-exported, so applications can mix manual instrumentation (plots, memory profiling, frame marks) with the automatic tracing bridge in the same process.

Common Use Cases

  • Bolting a profiler onto an already-instrumented service - a Rust service that already uses tracing for structured logging adds TracyLayer to see the same spans rendered as a live, interactive flame/zone timeline in Tracy’s GUI.
  • Hunting hot spots in game or real-time engines - engines and simulation loops use Tracy’s remote, low-overhead capture to find per-frame bottlenecks without attaching a heavyweight sampling profiler.
  • Conditionally shipping profiling in release builds - the enable feature flag lets teams compile tracing-tracy into production binaries but keep it inert unless explicitly turned on, avoiding the network-exposure concerns of always-on broadcast.
  • Correlating async task behavior across threads - because Tracy visualizes context switches and per-thread zones together, teams instrumenting tokio-based async code use it to see where spans hop threads or get delayed by the scheduler.

Under The Hood

Architecture TracyLayer implements tracing_subscriber::Layer, hooking on_new_span, on_enter, on_exit, on_event, and on_record to translate tracing’s span/event model into Tracy zones and messages; each thread keeps a thread-local stack (VecCell<(Span, u64)>) of currently active spans so exits can be matched to the correct zone even under nested or re-entrant spans. Formatting of span fields is delegated to a generic Config trait (DefaultConfig by default), decoupling the wire-format concerns from the tracing hook logic. The workspace is layered three deep: tracing-tracy depends on tracy-client (a safe, ergonomic Rust API exposing Client/Span and once_cell-backed global client initialization), which itself depends on tracy-client-sys (raw unsafe FFI bindings whose build.rs compiles a vendored copy of the upstream C++ Tracy client via the cc crate). A change to the core Client/Span abstraction in the middle crate ripples through both the FFI layer beneath it and the tracing integration above it, and the workspace’s README maintains an explicit compatibility table pinning which tracy-client-sys/tracy-client/tracing-tracy versions correspond to which upstream Tracy release.

Tech Stack A Cargo workspace (edition 2021, MSRV tested down to 1.85 in CI) built on tracing-core and tracing-subscriber (fmt/registry features) for the tracing integration, once_cell for lazy global client state, optional rustc-demangle for symbol demangling, and windows-targets for Windows-specific FFI surface. The lowest-level crate, tracy-client-sys, uses the cc crate in its build.rs to compile a vendored, submodule-tracked copy of the C++ Tracy client library directly into the Rust binary, so no separate system install of Tracy is required to instrument a target application (only to run the Tracy GUI viewer itself). The bundled examples crate demonstrates usage in a wgpu + tokio application.

Code Quality Both tracing-tracy and tracy-client ship dedicated test modules and criterion-based benchmarks (harness = false, bench = true), and tracy-client additionally carries a loom-based concurrency test suite specifically to verify the correctness of global client lifetime management under interleaved thread schedules — an unusually rigorous check for a low-level profiling library. CI runs a compile-and-test matrix across nightly/stable/MSRV toolchains on Ubuntu, Windows, and macOS, exercising each crate with default features, no default features, and the full feature set individually, plus debug and release test runs. No clippy or rustfmt step is visible in the CI workflow, so style/lint enforcement appears to rely on maintainer discipline rather than automated gating.

What Makes It Unique Most Rust profiling options either require bespoke instrumentation calls or lean on sampling-based flamegraph tooling; tracing-tracy instead sits directly on top of the tracing ecosystem’s existing Span/Event model, so instrumentation teams have already written for logging or OpenTelemetry export can be repointed at Tracy’s remote, nanosecond-precision GUI with a single subscriber layer. Exposing Tracy’s advanced capture modes as a comprehensive set of independently toggleable Cargo features, each mapped directly to an upstream compile-time define, gives applications fine control over collection overhead and network exposure that few other tracing-to-profiler bridges offer.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search