You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Explore how to decouple remote_monitor from PrometheusClient #53
Decoupling remote_monitor.py from PrometheusClientService
Overview
This document explores how to decouple experiments/remote_monitor.py from PrometheusClientService. Currently, experiments/experiment_run_e2e.py orchestrates remote_monitor, which in turn orchestrates PrometheusClientService. They're tightly coupled around profiling PID management and lifecycle coordination.
# Lines 233-250 in remote_monitor.pyprofile_query_engine_pid=Noneifargs.profile_query_engine:
if (
constants.QUERY_ENGINE_PY_PROCESS_KEYWORDinargs.keywordsorconstants.QUERY_ENGINE_PY_CONTAINER_NAMEinargs.keywords
):
query_engine_pids=get_pids(constants.QUERY_ENGINE_PY_PROCESS_KEYWORD)
profile_query_engine_pid=query_engine_pids[
0
] # Take first PID for profilingelif (
constants.QUERY_ENGINE_RS_PROCESS_KEYWORDinargs.keywordsorconstants.QUERY_ENGINE_RS_CONTAINER_NAMEinargs.keywords
):
raiseNotImplementedError(
"Profiling for Rust query engine is not implemented yet"
)
Decoupling Strategies
1. Event-Driven Architecture
Replace direct coupling with event/message-based communication:
Create ProfilerService to handle Flink/Arroyo/QueryEngine profiling
Move profiling methods from remote_monitor.py to dedicated service
Use dependency injection to provide profiler to remote_monitor
Phase 2: Abstract Client Execution
Create ClientExecutor interface with PrometheusClientExecutor implementation
Remove direct PrometheusClientService dependency from remote_monitor
Allow remote_monitor to work with any client executor
Phase 3: Event-Driven Coordination
Implement experiment lifecycle events
PrometheusClient subscribes to profiling events
Remote monitor publishes experiment state changes
This approach would:
Remove direct service dependencies
Enable independent testing of components
Support different client implementations
Simplify remote_monitor responsibility to process monitoring + coordination
The key insight is that remote_monitor.py currently has two distinct responsibilities: process monitoring and experiment orchestration. Separating these concerns would enable the decoupling you're looking for.
For your experiment orchestration use case, I'd recommend:
Option 1: Custom Event Bus (No Dependencies)
✅ Zero dependencies
✅ Full control over behavior
✅ Easy to debug and test
✅ Fits your single-process model
❌ Need to implement yourself
Option 2: blinker (Minimal Dependency)
✅ Battle-tested (used by Flask)
✅ Clean API
✅ Good documentation
✅ Only ~10KB package
❌ One more dependency
Integration Example
# experiment_coordinator.pyfromeventsimportevent_bus, EventType, EventclassExperimentCoordinator:
def__init__(self):
self.services= {
'remote_monitor': RemoteMonitor(event_bus),
'profiler': ProfilingService(event_bus),
'prometheus_client': PrometheusClientService(event_bus)
}
defrun_experiment(self, args):
# Start monitoring firstself.services['remote_monitor'].start_monitoring(args)
# Services coordinate through events automatically# No more direct coupling!
Benefits of This Approach
The key benefits of this event-driven approach:
Loose Coupling: Services only know about events, not each other
Testability: Easy to mock events for unit testing
Extensibility: New services can listen to existing events
Debugging: Event flow is explicit and observable
For your CloudLab experiment orchestration, I'd start with the custom event bus since it's simple, has no dependencies, and perfectly fits your single-process coordination needs. You can always upgrade to blinker later if you need more features.
Next Steps
Phase 1: Implement the simple event bus
Phase 2: Extract profiling logic into ProfilingService
Phase 3: Refactor remote_monitor.py to use events instead of direct coupling
Phase 4: Update PrometheusClientService to publish/subscribe to events
Phase 5: Test and validate the decoupled system
This approach maintains all existing functionality while dramatically reducing coupling between components.
Activity
milindsrivastava1997 commentedon Mar 4, 2026
PRO-62 Explore how to decouple remote_monitor from PrometheusClient
milindsrivastava1997 commentedon Mar 4, 2026
From Claude code
Decoupling remote_monitor.py from PrometheusClientService
Overview
This document explores how to decouple
experiments/remote_monitor.pyfromPrometheusClientService. Currently,experiments/experiment_run_e2e.pyorchestratesremote_monitor, which in turn orchestratesPrometheusClientService. They're tightly coupled around profiling PID management and lifecycle coordination.Current Architecture Analysis
Key Files Examined
/home/milind/Desktop/cmu/research/sketch_db_for_prometheus/code/Utilities/experiments/remote_monitor.py/home/milind/Desktop/cmu/research/sketch_db_for_prometheus/code/Utilities/experiments/experiment_run_e2e.py/home/milind/Desktop/cmu/research/sketch_db_for_prometheus/code/Utilities/experiments/experiment_utils/services/prometheus_client_service.py/home/milind/Desktop/cmu/research/sketch_db_for_prometheus/code/Utilities/experiments/experiment_utils/services/remote_monitor_service.pyCurrent Coupling Points
Direct Instantiation (
remote_monitor.py:293-308):remote_monitor.pydirectly imports and instantiatesPrometheusClientServiceprofile_query_engine_pid) directly to the serviceProfiling Coordination (
remote_monitor.py:274-337):remote_monitor.pymanages profiling for Flink/Arroyo PIDsConfiguration Coupling:
Architecture Flow
Current Code Examples
Direct Coupling in remote_monitor.py
Profiling PID Management
Decoupling Strategies
1. Event-Driven Architecture
Replace direct coupling with event/message-based communication:
2. Service Registry Pattern
Decouple service discovery and lifecycle management:
3. Abstract Profiling Manager
Extract profiling concerns into dedicated component:
4. Configuration Mediator
Centralize configuration management:
Recommended Decoupling Approach
Phase 1: Extract Profiling Logic
ProfilerServiceto handle Flink/Arroyo/QueryEngine profilingremote_monitor.pyto dedicated servicePhase 2: Abstract Client Execution
ClientExecutorinterface withPrometheusClientExecutorimplementationPhase 3: Event-Driven Coordination
This approach would:
The key insight is that
remote_monitor.pycurrently has two distinct responsibilities: process monitoring and experiment orchestration. Separating these concerns would enable the decoupling you're looking for.Event-Driven Implementation
Simple In-Process Event Bus (No Dependencies)
Refactored Remote Monitor
Decoupled PrometheusClient Service
Profiling Service
Library Options for Event Bus
1. No Dependencies (Recommended for Your Use Case)
The simple event bus shown above requires no external libraries. This is often the best choice for:
2. Lightweight Libraries
PyDispatcher (minimal dependency):
blinker (Flask's event system):
3. Full-Featured Message Brokers
Redis Pub/Sub (if you need cross-process events):
RabbitMQ/Celery (overkill for your use case):
# For distributed systems - probably too heavyRecommendation: Start Simple
For your experiment orchestration use case, I'd recommend:
Option 1: Custom Event Bus (No Dependencies)
Option 2: blinker (Minimal Dependency)
Integration Example
Benefits of This Approach
The key benefits of this event-driven approach:
For your CloudLab experiment orchestration, I'd start with the custom event bus since it's simple, has no dependencies, and perfectly fits your single-process coordination needs. You can always upgrade to
blinkerlater if you need more features.Next Steps
ProfilingServiceremote_monitor.pyto use events instead of direct couplingPrometheusClientServiceto publish/subscribe to eventsThis approach maintains all existing functionality while dramatically reducing coupling between components.
milindsrivastava1997 commentedon Mar 4, 2026
PRO-62