Skip to content

Conversation

artemziborev
Copy link

Fixes #369
Design discussion issue (if applicable) #

Changes

This PR improves the user-events logs benchmark by adding automatic enable/disable management for the user events listener using RAII guards. The benchmark now automatically enables the listener when tests start and disables it when they complete, ensuring proper cleanup even if the benchmark panics.

Key Changes:

  • Added UserEventsListenerGuard RAII guard for automatic listener management
  • Updated benchmark results in comments with current performance data
  • Added graceful fallback for systems without user events support
  • Enabled required features by default to fix code analysis warnings

Technical Details:

  • Uses echo commands to enable/disable listener: /sys/kernel/debug/tracing/events/user_events/myprovider_L2K1/enable
  • Preserves listener state (doesn't disable if already enabled)
  • Provides detailed logging for debugging
  • Handles systems without user events support gracefully

Merge requirement checklist

  • CONTRIBUTING guidelines followed
  • Unit tests added/updated (if applicable) - All existing tests pass
  • Appropriate CHANGELOG.md files updated for non-trivial, user-facing changes
  • Changes in public API reviewed (if applicable) - No public API changes

@artemziborev artemziborev requested a review from a team as a code owner August 6, 2025 07:03
Copy link

codecov bot commented Aug 6, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 48.0%. Comparing base (d7784b1) to head (871b652).

Additional details and impacted files
@@          Coverage Diff          @@
##            main    #420   +/-   ##
=====================================
  Coverage   47.9%   48.0%           
=====================================
  Files         69      69           
  Lines       9860    9855    -5     
=====================================
  Hits        4731    4731           
+ Misses      5129    5124    -5     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@lalitb lalitb requested a review from Copilot August 6, 2025 15:34
Copilot

This comment was marked as outdated.

}

// Enable listener with RAII guard
let _guard = UserEventsListenerGuard::enable("myprovider")
Copy link
Member

Choose a reason for hiding this comment

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

I don't think this works as the tracepoint name will not exist at this point! This should be done after the provider is built, which will build the user_events exporter, which will create the tracepoint names.

Copy link
Author

Choose a reason for hiding this comment

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

Moved UserEventsListenerGuard::enable(PROVIDER_NAME) to occur after building the provider in all benchmarks, ensuring tracepoints exist first.

@artemziborev artemziborev changed the title Feat/auto listener benchmark feat: auto listener benchmark Aug 13, 2025
let provider = setup_provider_default();
// Enable listener with RAII guard (after provider is built so tracepoints exist)
let _guard = UserEventsListenerGuard::enable(PROVIDER_NAME).unwrap_or_else(|e| {
Copy link
Member

Choose a reason for hiding this comment

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

this means the listener is always enabled when the benchmarks is run. What we really want is for the benchmark to run this with and without enabling the listener. A criterion bench group - like group.bench_function(enabled) and group.bench_function(disabled).

Copy link
Member

@lalitb lalitb Aug 13, 2025

Choose a reason for hiding this comment

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

Oh yes, good find - seems I missed while reviewing.

Copy link
Author

Choose a reason for hiding this comment

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

Thank you for the excellent suggestion! You're absolutely right - the current approach always enables the listener, which doesn't provide meaningful performance comparison data.
I've restructured all benchmark functions to use criterion bench groups that run both with and without the listener enabled:
Each benchmark now creates a benchmark_group with "disabled" and "enabled" variants
The "disabled" case runs without any listener management (baseline performance)
The "enabled" case uses the RAII guard to enable/disable the listener
This provides proper comparison data showing the actual overhead of enabling user events
The changes maintain all the safety benefits (RAII guards, proper cleanup) while giving us the performance comparison we need. Users can now see the baseline performance vs. the overhead of having the listener active.
This addresses the core issue you identified - we now have proper benchmark data for both states rather than always running with the listener enabled.

Copy link
Member

@cijothomas cijothomas left a comment

Choose a reason for hiding this comment

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

@lalitb lalitb self-requested a review August 13, 2025 23:50
Copy link
Author

@artemziborev artemziborev left a comment

Choose a reason for hiding this comment

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

All reviewer comments have been addressed:

✅ Fixed command injection risk by using sudo tee with piped stdin instead of shell commands
✅ Replaced hardcoded "myprovider" with PROVIDER_NAME constant
✅ Extracted duplicated dummy guard creation into dummy_guard() helper method
✅ Added USER_EVENTS_PROVIDER_SUFFIX constant to eliminate magic string
✅ Moved listener enabling to occur after provider creation (tracepoints exist)
✅ Removed experimental features from default in Cargo.toml
✅ Restructured benchmarks to compare enabled/disabled listener performance using criterion groups
✅ Reverted non-user-facing changes from CHANGELOG

The benchmarks now properly compare performance with and without the listener enabled, providing meaningful data for both states.

Copilot

This comment was marked as outdated.

@artemziborev artemziborev requested a review from Copilot August 14, 2025 10:47
Copilot

This comment was marked as outdated.

@artemziborev artemziborev requested a review from Copilot August 14, 2025 10:57
Copilot

This comment was marked as outdated.

@artemziborev artemziborev requested a review from Copilot August 14, 2025 13:04
Copilot

This comment was marked as outdated.

@artemziborev artemziborev requested a review from Copilot August 14, 2025 13:10
Copilot

This comment was marked as outdated.

@artemziborev artemziborev requested a review from Copilot August 14, 2025 13:18
Copilot

This comment was marked as outdated.

@artemziborev artemziborev requested a review from Copilot August 14, 2025 13:27
Copilot

This comment was marked as outdated.

@artemziborev artemziborev requested review from hdost and Copilot August 14, 2025 13:36
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR implements automatic listener management for user-events logs benchmarking by introducing RAII guards that enable/disable the user events listener, eliminating the need for manual listener management and ensuring proper cleanup.

  • Added UserEventsListenerGuard struct with automatic enable/disable functionality using RAII pattern
  • Updated all benchmark functions to test both enabled and disabled listener states automatically
  • Enhanced benchmark results documentation with current performance data and automatic management details

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
opentelemetry-user-events-logs/benches/logs.rs Implements RAII guard for automatic listener management and updates benchmark functions to test both enabled/disabled states
opentelemetry-user-events-logs/CHANGELOG.md Adds empty line to changelog (no functional changes)

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

/// /sys/kernel/debug/tracing/events/user_events/myprovider_L2K1/enable
/// For more details, see the Linux kernel documentation on user_events:
/// https://docs.kernel.org/trace/user_events.html
const USER_EVENTS_PROVIDER_SUFFIX: &str = "_L2K1";
Copy link
Preview

Copilot AI Aug 14, 2025

Choose a reason for hiding this comment

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

The hardcoded suffix "_L2K1" is system-specific and may not work across different systems or kernel versions. Consider dynamically discovering the actual suffix by scanning the directory /sys/kernel/debug/tracing/events/user_events/ for providers starting with the provider name, or document this limitation more prominently.

Suggested change
const USER_EVENTS_PROVIDER_SUFFIX: &str = "_L2K1";
// Dynamically discover the actual provider directory (with suffix) at runtime.
/// Returns the full provider directory name (e.g., "myprovider_L2K1") by scanning
/// /sys/kernel/debug/tracing/events/user_events/ for a directory starting with the provider name.
fn get_user_events_provider_dir(provider_name: &str) -> io::Result<String> {
let dir = "/sys/kernel/debug/tracing/events/user_events/";
for entry in fs::read_dir(dir)? {
let entry = entry?;
let file_name = entry.file_name();
let file_name_str = file_name.to_string_lossy();
if file_name_str.starts_with(provider_name) {
return Ok(file_name_str.into_owned());
}
}
Err(io::Error::new(
io::ErrorKind::NotFound,
format!("Provider directory for '{}' not found in {}", provider_name, dir),
))
}

Copilot uses AI. Check for mistakes.

/// * `Ok(String)` - The status content if user events are available
/// * `Err(String)` - Error message if user events are not available
fn check_user_events_available() -> Result<String, String> {
match fs::read_to_string("/sys/kernel/tracing/user_events_status") {
Copy link
Preview

Copilot AI Aug 14, 2025

Choose a reason for hiding this comment

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

The path /sys/kernel/tracing/user_events_status is hardcoded and differs from the debugfs path pattern used elsewhere (/sys/kernel/debug/tracing/). Consider defining this as a constant or documenting why different paths are used for different operations.

Copilot uses AI. Check for mistakes.

if self.is_dummy {
return;
}

Copy link
Preview

Copilot AI Aug 14, 2025

Choose a reason for hiding this comment

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

The disable_path variable is constructed using self.provider_name which could be the dummy provider name if this is a dummy guard. However, the is_dummy check occurs after the path construction. This could lead to attempting to write to an invalid path. Move the is_dummy check before any path operations.

Suggested change
// Skip cleanup for dummy guards
if self.is_dummy {
return;
}
let disable_path = format!(
"/sys/kernel/debug/tracing/events/user_events/{}{}/enable",
self.provider_name, USER_EVENTS_PROVIDER_SUFFIX
);

Copilot uses AI. Check for mistakes.

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.

Benchmarks for user-events should automatically enabled and disable listener
4 participants