feat(v1.1): Async API, Typed Events, and Filtering#58
Merged
Conversation
## Async Streaming API (#54) - AsyncEtwSession with async context manager support - async for iteration over events - Event callbacks with on_event() - EventBatcher for batch processing - gather_events() for concurrent session monitoring - stream_to_queue() for producer/consumer patterns ## Typed Events (#55) - TypedEvent base class with common properties - ProcessStartEvent, ProcessStopEvent for process monitoring - ThreadStartEvent, ThreadStopEvent for thread tracking - ImageLoadEvent for DLL/module loading - DnsQueryEvent, DnsResponseEvent for DNS monitoring - TcpConnectEvent, TcpDisconnectEvent for network - to_typed_event() auto-conversion function - register_event_type() for custom events ## Event Filtering (#56) - EventFilterBuilder with fluent API - Filter by: event_id, process_id, level, opcode - Property filters: equals, contains, startswith, regex - Combine filters with & (AND) and | (OR) - Custom predicate support - Convenience functions: event_id_filter, level_filter, etc. ## Demos - demo_async_api.py - Async patterns demonstration - demo_typed_events.py - Typed event usage - demo_filtering.py - Filter builder examples Closes #54, #55, #56 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use KernelSession methods instead of PyKernelFlags - Use provider GUID instead of name for EtwProvider - Add is_running() check before stop() 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use EtwProvider.dns_client().level(5) instead of EtwProvider(...).with_level(5) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use EtwProvider.dns_client() instead of constructor with name - Use KernelSession with enable_* methods - Handle providers without GUID in profiles example - Add is_running() checks before stop() 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
AsyncEtwSession's context manager now doesn't auto-start, allowing providers to be added after entering the context. The events() method auto-starts the session when iteration begins, ensuring providers are registered before the session starts. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove unused imports (process_filter, property_filter, KernelFlags, Sequence) - Fix f-strings without placeholders - Sort import blocks - Remove unused session variable in demo_typed_events - Rename keywords parameter to _keywords (reserved for future use) - Simplify _should_process with all() 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add examples/ to black and ruff file patterns - Add include patterns in pyproject.toml for ruff - Fix cargo-clippy to not fail on pyo3 build issues in pre-commit env - Apply auto-fixes from pre-commit (trailing whitespace, EOF) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace pip with uv pip (5-10x faster package installs) - Use astral-sh/setup-uv@v4 with cache enabled - Add cargo cache for build-wheels job - Include examples/ in black and ruff checks 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
uv.lock file doesn't exist in this project, so set cache-dependency-glob to empty string to prevent failure. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Ubuntu 24.04 has externally managed Python, so --system flag fails. Use uv venv for all jobs to ensure consistent behavior. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Workspace Cargo.toml doesn't have package field, need to specify the crate-specific Cargo.toml path. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove continue-on-error from all jobs except mypy (still soft fail) - Remove if: always() to ensure proper job dependencies - Fix Python test to run from temp dir (avoid src/ import conflict) - Fix Rust test lifetime error in pyo3::Python::with_gil usage 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The test was failing because the default keywords_any value (0xFFFFFFFFFFFFFFFF) was filtering out events with keywords=0. Added .with_keywords_any(0) to disable the keywords filter for this level-only test. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Refactor discovery.rs to use ? operator instead of explicit map_err - Remove test_error_conversion_to_pyerr that required Python interpreter - Add test_error_messages to verify error string formatting instead 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Collapse nested if in etl_reader.rs:109 - Use ? operator instead of explicit map_err in etl_reader.rs:158 - Use .copied() instead of .map(|&x| x) in event.rs:337 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The useless_conversion clippy lint is triggered by pyo3 macro-generated code when impl From<CustomError> for PyErr is defined. This is a known pyo3 issue (PyO3/pyo3#3370) and not a real problem in our code. Also fixes: - Use is_some_and instead of map_or(false, ...) in filter.rs - Collapse nested if statements in etl_reader.rs - Use .copied() instead of .map(|&x| x) in event.rs 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace manual impl Default for TraceLevel with derive + #[default] - Replace manual impl Default for TraceMode with derive + #[default] - Use struct update syntax instead of field reassignment after default() 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The pytest was finding src/pyetwkit directory when running tests, causing 'ModuleNotFoundError: No module named pyetwkit_core' because _core.py tries to import from the native extension. Copying tests to temp dir ensures only the installed wheel is used. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The union type syntax (X | None) requires Python 3.10+. Adding 'from __future__ import annotations' allows this syntax to work in Python 3.9 by treating annotations as strings. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR implements all v1.1 Enhanced Core features:
Async Streaming API (#54)
AsyncEtwSession- Modern async/await ETW sessionon_event()EventBatcherfor efficient batch processinggather_events()for concurrent monitoringstream_to_queue()for producer/consumer patternsTyped Events (#55)
TypedEventbase class with common propertiesProcessStartEvent,ProcessStopEventThreadStartEvent,ThreadStopEventImageLoadEventDnsQueryEvent,DnsResponseEventTcpConnectEvent,TcpDisconnectEventto_typed_event()auto-conversionregister_event_type()for custom eventsEvent Filtering (#56)
EventFilterBuilderwith fluent API&(AND) and|(OR)Example Usage
Async API
Typed Events
Filtering
Demo Scripts
examples/demo_async_api.pyexamples/demo_typed_events.pyexamples/demo_filtering.pyCloses
Test plan
🤖 Generated with Claude Code