Skip to content

feat: decouple instrumentation span level from log verbosity#157

Open
randygrok wants to merge 1 commit intomainfrom
randygrok/restrict-engine-api
Open

feat: decouple instrumentation span level from log verbosity#157
randygrok wants to merge 1 commit intomainfrom
randygrok/restrict-engine-api

Conversation

@randygrok
Copy link
Contributor

@randygrok randygrok commented Mar 5, 2026

Description

Add EV_TRACE_LEVEL env var to control OTLP span export level independently from RUST_LOG stdout log verbosity. When OTLP is enabled, per-layer filtering applies separate filters to fmt layer (RUST_LOG) and OTLP layer (EV_TRACE_LEVEL). This allows operators to run with RUST_LOG=info (clean logs) while exporting debug-level spans to observability backends like Jaeger.

Type of Change

  • New feature (non-breaking change which adds functionality)
  • Documentation update

Related Issues

Closes #156

Checklist

  • I have performed a self-review of my code
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • New and existing unit tests pass locally with my changes

Testing

  • Built project: just build
  • Lint: just lint
  • Format check: just fmt-check
  • Tests: just test ✓ (all 17 test suites pass)
  • Manual verification: Confirmed traces visible in Jaeger UI with EV_TRACE_LEVEL=debug and clean logs with RUST_LOG=info

Summary by CodeRabbit

  • New Features

    • Added EV_TRACE_LEVEL environment variable to independently control OTLP span export verbosity, separate from stdout logging controlled by RUST_LOG.
  • Documentation

    • Added OTLP Tracing section to README with configuration examples and reference table for controls and defaults.

Add EV_TRACE_LEVEL env var to control OTLP span export level independently
from RUST_LOG stdout log verbosity. When OTLP is enabled, per-layer filtering
applies separate filters to fmt layer (RUST_LOG) and OTLP layer (EV_TRACE_LEVEL).

Allows operators to run with RUST_LOG=info (clean logs) while exporting
debug-level spans to observability backends like Jaeger.
@randygrok randygrok requested a review from a team as a code owner March 5, 2026 17:23
@coderabbitai
Copy link

coderabbitai bot commented Mar 5, 2026

📝 Walkthrough

Walkthrough

The pull request decouples OTLP span export verbosity from stdout log verbosity by introducing a new EV_TRACE_LEVEL environment variable, enabling independent control of instrumentation depth and log output in tracing configuration. Documentation and implementation are updated to support this separation.

Changes

Cohort / File(s) Summary
Documentation
CHANGELOG.md, README.md
Added documentation for the new EV_TRACE_LEVEL environment variable, including OTLP tracing configuration guidance, interaction with RUST_LOG, usage examples, and a reference table of controls and defaults.
Tracing Configuration
bin/ev-reth/src/main.rs
Introduced OTLP-aware tracing initialization with per-layer filtering: stdout logging respects RUST_LOG, while OTLP span exporter uses separate EV_TRACE_LEVEL filter. Includes conditional logic to fall back to simple registry if OTLP is unavailable. Added EV_TRACE_LEVEL_ENV constant and refactored tracing setup into init_tracing() function. Imported Layer trait for layer-specific filtering.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 Hops of joy through tracer's way,
Logs and spans now separate play,
Debug depth flows to OTLP's keep,
While info logs stay clean and deep,
Observability without the noise—
A rabbit's delight, a coder's choice!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: decoupling the control of OTLP span export level from stdout log verbosity using a new environment variable.
Linked Issues check ✅ Passed The changes fully implement the objectives from issue #156: adds EV_TRACE_LEVEL env var, implements per-layer filtering in init_tracing(), and enables independent control of span level from log verbosity.
Out of Scope Changes check ✅ Passed All changes are directly related to the linked issue: EV_TRACE_LEVEL env var, tracing configuration updates, documentation, and CHANGELOG entries are all in scope.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description check ✅ Passed The pull request description comprehensively covers all required sections: detailed description of changes, type of change (new feature and documentation update), related issue link, completed checklist items, thorough testing verification, and clear use case example.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch randygrok/restrict-engine-api

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
bin/ev-reth/src/main.rs (1)

85-96: ⚠️ Potential issue | 🟡 Minor

Log statement before tracing initialization will be silently dropped.

The info! macro at line 86 is called before init_tracing() at line 96. Since no subscriber is registered yet, this log will be silently discarded and never appear in output.

Consider moving the log after init_tracing() or removing it if redundant with the launch success message at line 116.

🔧 Suggested fix
 fn main() {
-    info!("=== EV-RETH NODE STARTING ===");
-
     reth_cli_util::sigsegv_handler::install();

     // Enable backtraces unless a RUST_BACKTRACE value has already been explicitly provided.
     if std::env::var_os("RUST_BACKTRACE").is_none() {
         std::env::set_var("RUST_BACKTRACE", "1");
     }

     // initialize tracing (with optional OTLP support based on env vars)
     init_tracing();

+    info!("=== EV-RETH NODE STARTING ===");
+
     if let Err(err) =
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@bin/ev-reth/src/main.rs` around lines 85 - 96, The initial info! log is
emitted before tracing is initialized, so it will be dropped; move the
info!("=== EV-RETH NODE STARTING ===") call to after init_tracing() (or remove
it if redundant with the later launch success message) so that the message is
logged by the subscriber; locate the log invocation in main() and the
init_tracing() call and reorder accordingly to ensure tracing is initialized
before emitting the info! message.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@bin/ev-reth/src/main.rs`:
- Around line 85-96: The initial info! log is emitted before tracing is
initialized, so it will be dropped; move the info!("=== EV-RETH NODE STARTING
===") call to after init_tracing() (or remove it if redundant with the later
launch success message) so that the message is logged by the subscriber; locate
the log invocation in main() and the init_tracing() call and reorder accordingly
to ensure tracing is initialized before emitting the info! message.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fc22b28f-8693-4b65-bf66-cca0a14ce571

📥 Commits

Reviewing files that changed from the base of the PR and between 0a1d55c and e419622.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • README.md
  • bin/ev-reth/src/main.rs

@claude
Copy link

claude bot commented Mar 5, 2026

Claude finished @randygrok's task —— View job


PR Review: EV_TRACE_LEVEL Feature

Review Checklist:

  • Read and analyze changed files
  • Review code quality and best practices
  • Check for potential bugs or issues
  • Evaluate performance considerations
  • Assess security concerns
  • Analyze test coverage
  • Provide comprehensive feedback

📋 Summary

This PR successfully implements the EV_TRACE_LEVEL environment variable to decouple OTLP span export verbosity from stdout logging controlled by RUST_LOG. The implementation is clean, well-documented, and addresses a legitimate operational need.

✅ Strengths

  1. Clear Separation of Concerns: The implementation properly separates stdout logging (RUST_LOG) from OTLP tracing (EV_TRACE_LEVEL) using per-layer filtering
  2. Robust Fallback Logic: Graceful fallback chain: EV_TRACE_LEVELRUST_LOG"info"
  3. Documentation Excellence: Comprehensive README updates with clear examples and reference table
  4. Minimal Surface Area: Focused change that doesn't affect existing behavior when EV_TRACE_LEVEL is not set

⚠️ Issues Found

Critical Issue: Log Before Tracing Initialization

Location: bin/ev-reth/src/main.rs:86

The info!("=== EV-RETH NODE STARTING ===") log statement is called before init_tracing() at line 96. Since no tracing subscriber is registered yet, this log message will be silently dropped and never appear in any output.

Fix: Move the log statement after init_tracing() call:

fn main() {
    reth_cli_util::sigsegv_handler::install();

    // Enable backtraces unless a RUST_BACKTRACE value has already been explicitly provided.
    if std::env::var_os("RUST_BACKTRACE").is_none() {
        std::env::set_var("RUST_BACKTRACE", "1");
    }

    // initialize tracing (with optional OTLP support based on env vars)
    init_tracing();
    
    info!("=== EV-RETH NODE STARTING ===");  // Move here

    if let Err(err) = 
        // ... rest remains the same

📊 Code Quality Assessment

Aspect Rating Notes
Implementation ✅ Good Clean separation of concerns, proper error handling
Documentation ✅ Excellent Comprehensive README with examples and reference table
Error Handling ✅ Good Proper fallback logic for environment variable parsing
Testing ⚠️ Manual Only Only manual verification mentioned, no unit tests for tracing config

🔍 Detailed Analysis

Security Considerations

  • ✅ No security concerns - environment variables are read-only and used for configuration
  • ✅ No sensitive data exposure through tracing configuration

Performance Considerations

  • ✅ Minimal performance impact - configuration only happens at startup
  • ✅ Per-layer filtering is more efficient than global filtering for mixed verbosity needs

Potential Improvements

  1. Add Unit Tests: Consider adding tests for the init_tracing() function to verify:

    • Proper fallback behavior when EV_TRACE_LEVEL is not set
    • Correct layer configuration with various environment variable combinations
    • OTLP config parsing edge cases
  2. Environment Variable Validation: Consider validating EV_TRACE_LEVEL format at startup and providing helpful error messages for invalid filter expressions

Documentation Quality

The README updates are exemplary:

  • Clear explanation of the new feature
  • Practical usage examples
  • Reference table showing variable interactions
  • Good integration with existing documentation structure

🏁 Final Recommendation

Approve with Minor Fix Required

This is a solid implementation that addresses a real operational need. The only blocking issue is the misplaced log statement that will be silently dropped. Once that's fixed, this PR is ready to merge.

The feature successfully:

  • ✅ Decouples OTLP span verbosity from stdout logging
  • ✅ Maintains backward compatibility
  • ✅ Provides clear documentation and examples
  • ✅ Uses proper Rust tracing patterns

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.

Decouple instrumentation span level from log verbosity

2 participants