Adds tracing instrumentation to Rust code. Use when adding [instrument], debugging systems, or viewing logs.
Add #[instrument] to functions that need tracing:
use tracing::instrument;
#[instrument(level = "debug", skip_all)]
fn my_system(query: Query<&Player>, state: Res<GameState>) {
// Function body
}
Logs are written to logs/game_{timestamp}.log.
View the latest log:
tail -f logs/$(ls -t logs | head -1)
| Pattern | When to Use |
|---|---|
skip_all | Default for systems (avoids logging large Bevy types) |
| + |
skip(self)fields()| Methods where you want specific context |
ret | Functions with meaningful return values |
fields(key = ?value) | Add custom context (positions, counts, entities) |
// System with skip_all (most common)
#[instrument(level = "debug", skip_all)]
fn handle_player_move(...) { }
// Method with explicit fields
#[instrument(level = "debug", skip(self), fields(pos = ?pos, entity = ?entity))]
pub fn occupy(&mut self, pos: GridPosition, entity: Entity) { }
// Log return value
#[instrument(level = "debug", ret)]
pub fn apply_defense(raw_damage: i32, defense: i32) -> i32 { }
// Computed field
#[instrument(level = "debug", skip_all, fields(entity_count = layout.entities().len()))]
fn spawn_entities(...) { }
// Deferred field (computed inside function body)
#[instrument(level = "debug", skip_all, fields(coal_qty, ore_qty))]
fn process_crafting(state: &ForgeCraftingState) {
let coal_qty = state.coal_slot.as_ref().map(|(_, q)| *q).unwrap_or(0);
let ore_qty = state.ore_slot.as_ref().map(|(_, q)| *q).unwrap_or(0);
tracing::Span::current().record("coal_qty", coal_qty);
tracing::Span::current().record("ore_qty", ore_qty);
// ... rest of logic
}
Filter in src/main.rs: "warn,game=debug"
debug level for game cratewarn+ for dependenciesSpan events: FmtSpan::ENTER | FmtSpan::CLOSE
ENTER logs when spans start (shows initial field values)CLOSE logs when spans end (shows deferred field values from Span::current().record())use tracing::instrument;level = "debug"skip_all for systemsfields() only for key contextLogs are stored as JSON Lines. Use jq to filter efficiently:
LOG=$(ls -t logs/*.log | head -1)
# Errors only
jq 'select(.level == "ERROR")' "$LOG"
# Specific module
jq 'select(.target | contains("combat"))' "$LOG"
# Last N entries
tail -50 "$LOG" | jq .
# Span entries for function
jq 'select(.span.name == "handle_player_move")' "$LOG"
# Events with specific field
jq 'select(.fields.entity != null)' "$LOG"