Trace File Operations - The Renacer Book - Pure Rust System Call Tracing
Description: A comprehensive guide to renacer: syscall tracing, DWARF correlation, and performance analysis

# Example: Trace File Operations

This example shows how to use Renacer to trace and debug file operations in your applications.

## Scenario: Debug Configuration File Loading

Your application can't find its configuration file. Let's trace which files it tries to open.

### Step 1: Basic File Tracing

    $ renacer -e 'trace=file' -- ./myapp

Output:

    openat(AT_FDCWD, "/etc/myapp/config.toml", O_RDONLY) = -ENOENT
    openat(AT_FDCWD, "/home/user/.config/myapp.toml", O_RDONLY) = -ENOENT
    openat(AT_FDCWD, "./config.toml", O_RDONLY) = 3
    read(3, "database_url = \"postgres://...\"\n", 4096) = 156
    close(3) = 0

Analysis:

- First two locations fail (`-ENOENT` = file not found)
- Third location succeeds (returns FD 3)
- Config file read successfully

### Step 2: Focus on Open Calls Only

Too much output? Filter to just file opens:

    $ renacer -e 'trace=openat' -- ./myapp

Output:

    openat(AT_FDCWD, "/etc/myapp/config.toml", O_RDONLY) = -ENOENT
    openat(AT_FDCWD, "/home/user/.config/myapp.toml", O_RDONLY) = -ENOENT
    openat(AT_FDCWD, "./config.toml", O_RDONLY) = 3

Much cleaner! Now you can see the exact search order.

### Step 3: Add Source Correlation

Which code is doing this?

    $ renacer --source -e 'trace=openat' -- ./myapp

Output:

    openat(AT_FDCWD, "/etc/myapp/config.toml", O_RDONLY) = -ENOENT   [src/config.rs:42 in load_config]
    openat(AT_FDCWD, "/home/user/.config/myapp.toml", O_RDONLY) = -ENOENT   [src/config.rs:43 in load_config]
    openat(AT_FDCWD, "./config.toml", O_RDONLY) = 3   [src/config.rs:44 in load_config]

Perfect! Now you know `src/config.rs:42-44` is checking these locations.

## Scenario: Excessive File Access

Your app is slow during startup. Let's find out why.

### Step 1: Count File Operations

    $ renacer -c -e 'trace=file' -- ./slow-app

Output:

    System Call Summary:
    ====================
    Syscall          Calls    Total Time    Avg Time
    openat           1247     890.2ms       0.714ms
    fstat            1247     156.3ms       0.125ms
    read             3741     445.1ms       0.119ms
    close            1224     34.5ms        0.028ms

Problem Found: 1,247 `openat` calls taking 890ms (60% of startup time)!

### Step 2: Investigate What's Being Opened

    $ renacer -e 'trace=openat' -- ./slow-app | head -20

Output:

    openat(AT_FDCWD, "/usr/share/icons/hicolor/16x16/apps/icon001.png", O_RDONLY) = 3
    openat(AT_FDCWD, "/usr/share/icons/hicolor/16x16/apps/icon002.png", O_RDONLY) = 3
    openat(AT_FDCWD, "/usr/share/icons/hicolor/16x16/apps/icon003.png", O_RDONLY) = 3
    ...

Root Cause: Loading 1,247 icon files individually!

Solution: Lazy-load icons or bundle them into a single resource file.

## Scenario: Find Permission Errors

Your app crashes with "permission denied". Which file?

### Step 1: Filter to Errors

    $ renacer -e 'trace=file' -- ./app 2>&1 | grep -E 'EACCES|EPERM'

Output:

    openat(AT_FDCWD, "/var/log/myapp.log", O_WRONLY|O_CREAT|O_APPEND, 0644) = -EACCES

Found it! Can't write to `/var/log/myapp.log` (permission denied).

Solution: Either fix permissions or change log location to `~/.local/share/myapp/log`.

### Step 2: Verify the Fix

After changing to home directory:

    $ renacer -e 'trace=openat,write' -- ./app

Output:

    openat(AT_FDCWD, "/home/user/.local/share/myapp/log", O_WRONLY|O_CREAT|O_APPEND, 0644) = 3
    write(3, "[INFO] Application started\n", 28) = 28

Success! File opens and writes complete successfully.

## Scenario: Track File Modifications

Which files does your app write to?

### Step 1: Trace Writes Only

    $ renacer -e 'trace=write,openat' -- ./data-processor input.csv

Output:

    openat(AT_FDCWD, "input.csv", O_RDONLY) = 3
    openat(AT_FDCWD, "output.csv", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 4
    write(4, "name,age,email\n", 15) = 15
    write(4, "Alice,30,alice@example.com\n", 28) = 28
    write(4, "Bob,25,bob@example.com\n", 24) = 24

Observation: App reads `input.csv`, writes to `output.csv`.

### Step 2: Export for Analysis

    $ renacer --format json -e 'trace=write' -- ./data-processor input.csv > writes.json

Then analyze with `jq`:

    $ jq '.syscalls[] | select(.name == "write") | .args.count' writes.json | paste -sd+ | bc
    67

Result: 67 bytes written total.

## Scenario: Detect Resource Leaks

Are files being closed properly?

### Step 1: Compare Opens vs. Closes

    $ renacer -e 'trace=openat,close' -- ./leaky-app

Output:

    openat(AT_FDCWD, "file1.txt", O_RDONLY) = 3
    openat(AT_FDCWD, "file2.txt", O_RDONLY) = 4
    openat(AT_FDCWD, "file3.txt", O_RDONLY) = 5
    # ... program continues ...
    # No close() calls!

Problem: Files opened but never closed - file descriptor leak!

### Step 2: Use Statistics to Confirm

    $ renacer -c -e 'trace=openat,close' -- ./leaky-app

Output:

    Syscall          Calls    Errors
    openat           100      0
    close            0        0

Confirmed: 100 opens, 0 closes = file descriptor leak.

## Best Practices

### 1. Start Broad, Narrow Down

    # Step 1: See all file operations
    renacer -e 'trace=file' -- ./app

    # Step 2: Too noisy? Remove metadata calls
    renacer -e 'trace=file,!/fstat/,!/close/' -- ./app

    # Step 3: Focus on specific operations
    renacer -e 'trace=openat,read,write' -- ./app

### 2. Combine with Source Correlation

    # Always use --source for debugging
    renacer --source -e 'trace=file' -- ./app

Tells you exactly which code line is making each syscall.

### 3. Use Statistics for Performance

    # Find slow file operations
    renacer -c -e 'trace=file' -- ./app

Shows which file operations take the most time.

### 4. Export for Later Analysis

    # Export to JSON
    renacer --format json -e 'trace=file' -- ./app > file-ops.json

    # Analyze with jq
    jq '.syscalls[] | select(.return.error != null)' file-ops.json

Filter to errors, slow operations, specific files, etc.

## Common Patterns

### Pattern 1: Find Missing Files

    renacer -e 'trace=openat' -- ./app 2>&1 | grep ENOENT

Shows all "file not found" errors.

### Pattern 2: Find Excessive I/O

    renacer -c -e 'trace=read,write' -- ./app

Count read/write calls and total time.

### Pattern 3: Track Specific File

    renacer -e 'trace=file' -- ./app 2>&1 | grep config.toml

Filter output to specific file path.

### Pattern 4: Debug File Permissions

    renacer -e 'trace=file' -- ./app 2>&1 | grep -E 'EACCES|EPERM'

Find all permission denied errors.

## Next Steps

- Debug Performance Issues - Profile I/O bottlenecks
- Monitor Network Calls - Trace network operations
- Export to JSON/CSV - Analyze traces programmatically