Skip to content

Commit

Permalink
send more error context info, so it can be fixed
Browse files Browse the repository at this point in the history
  • Loading branch information
vysakh0 committed Aug 10, 2024
1 parent 26759f9 commit 9243ade
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 35 deletions.
8 changes: 6 additions & 2 deletions src/drd/cli/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@
VERSION = "0.13.9" # Update this as you release new versions


logging.basicConfig(level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
filename='dravid_monitor.log',
filemode='a')

# Also log to console


def parse_multiline_input(input_string):
Expand Down
27 changes: 13 additions & 14 deletions src/drd/cli/monitor/error_resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from ...utils.file_utils import get_file_content
from ...utils.input import confirm_with_user
import logging
import time


def monitoring_handle_error_with_dravid(error, line, monitor):
Expand Down Expand Up @@ -82,19 +81,19 @@ def monitoring_handle_error_with_dravid(error, line, monitor):
print_success("Fix applied.")

logger.info(f"User response to restart: ")
# if requires_restart:
# print_info("The applied fix requires a server restart.")
# restart_input = confirm_with_user(
# "Do you want to restart the server now? [y/N]: "
# )
# if restart_input:
print_info("Requesting server restart...")
monitor.perform_restart()
# else:
# print_info(
# "Server restart postponed. You may need to restart manually if issues persist.")
# else:
# print_info("The applied fix does not require a server restart.")
if requires_restart:
print_info("The applied fix requires a server restart.")
restart_input = confirm_with_user(
"Do you want to restart the server now? [y/N]: "
)
if restart_input:
print_info("Requesting server restart...")
monitor.perform_restart()
else:
print_info(
"Server restart postponed. You may need to restart manually if issues persist.")
else:
print_info("The applied fix does not require a server restart.")

logger.info("Error handling completed")
return True
48 changes: 35 additions & 13 deletions src/drd/cli/monitor/output_monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import select
import time
import threading
from collections import deque
import re

logger = logging.getLogger(__name__)
Expand All @@ -14,6 +15,9 @@ def __init__(self, monitor):
self.last_output_time = None
self.idle_detected = threading.Event()
self.stop_event = threading.Event()
self.buffer_size = 50 # Number of lines to keep in buffer
self.error_timeout = 2
logger.info("OutputMonitor initialized")

def start(self):
self.stop_event.clear()
Expand All @@ -27,9 +31,12 @@ def stop(self):
self.thread.join(timeout=5)

def _monitor_output(self):
error_buffer = []
output_buffer = deque(maxlen=self.buffer_size)
self.last_output_time = time.time()
error_detected = False
error_start_time = None

logger.info("Starting output monitoring")
while not self.stop_event.is_set():
if self.monitor.process is None or self.monitor.process.poll() is not None:
logger.info(
Expand All @@ -45,36 +52,51 @@ def _monitor_output(self):
if line:
line = line.strip()
print(line, flush=True)
logger.debug(f"Server output: {line}")
error_buffer.append(line)
if len(error_buffer) > 10:
error_buffer.pop(0)
output_buffer.append(line)

self.last_output_time = time.time()
self.monitor.retry_count = 0
if not self.monitor.processing_input.is_set():
self._check_for_errors(line, error_buffer)

if not error_detected:
error_detected = self._check_for_errors(line)
if error_detected:
error_start_time = time.time()
elif time.time() - error_start_time > self.error_timeout:
self._handle_error(list(output_buffer))
error_detected = False
output_buffer.clear()
else:
self._check_idle_state()
else:
self._check_idle_state()

if error_detected and time.time() - error_start_time > self.error_timeout:
self._handle_error(list(output_buffer))
error_detected = False
output_buffer.clear()

except Exception as e:
logger.error(f"Error in output monitoring: {str(e)}")
time.sleep(1) # Prevent rapid error logging

logger.info("Output monitoring stopped.")

def _check_for_errors(self, line, error_buffer):
def _check_for_errors(self, line):
logger.info(f"Checking for errors in line: {line}")
for error_pattern in self.monitor.error_handlers.keys():
if re.search(error_pattern, line, re.IGNORECASE):
full_error = '\n'.join(error_buffer)
logger.error(f"Error detected: {full_error}")
self.monitor.handle_error(full_error)
error_buffer.clear()
break
return True
return False

def _handle_error(self, error_context):
full_error = '\n'.join(error_context)
logger.error(f"Full error context:\n{full_error}")
self.monitor.handle_error(full_error)

def _check_idle_state(self):
current_time = time.time()
if (current_time - self.last_output_time > 5 and
not self.monitor.error_handling_in_progress.is_set() and
not self.monitor.processing_input.is_set()):
self.idle_detected.set()
logger.info("Idle state detected")
40 changes: 34 additions & 6 deletions src/drd/cli/monitor/server_monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from queue import Queue
from .input_handler import InputHandler
from .output_monitor import OutputMonitor
from ...utils import print_info, print_success, print_error, print_header, print_prompt
from ...utils import print_info, print_success, print_error, print_header, print_prompt, print_warning
from ...metadata.project_metadata import ProjectMetadataManager

import logging
Expand All @@ -30,7 +30,11 @@ def __init__(self, project_dir: str, error_handlers: dict, command: str):
self.error_handling_in_progress = threading.Event()
self.error_handlers = {
str(pattern): handler for pattern, handler in error_handlers.items()

}
self.error_handlers['default'] = self.default_error_handler
logger.info(
f"Initialized error handlers: {list(self.error_handlers.keys())}")

def start(self):
self.should_stop.clear()
Expand Down Expand Up @@ -120,16 +124,40 @@ def _main_loop(self):
finally:
self.stop()

def handle_error(self, error_msg):
def handle_error(self, error_context):
logger.info("Entering handle_error method")
self.error_handling_in_progress.set()
self.output_monitor.idle_detected.clear()

print_warning("An error has been detected. Here's the context:")

try:
for pattern, handler in self.error_handlers.items():
if re.search(pattern, error_msg, re.IGNORECASE):
handler(error_msg, self)
logger.info(f"Checking error pattern: {pattern}")
if re.search(pattern, error_context, re.IGNORECASE):
logger.info(f"Matched error pattern: {pattern}")
handler(error_context, self)
break
finally:
self.error_handling_in_progress.clear()
else:
logger.warning(
"No specific handler found for this error. Using default error handler.")
print_warning(
"No specific handler found for this error. Using default error handler.")
self.error_handlers['default'](error_context, self)
except Exception as e:
logger.error(f"Error during error handling: {str(e)}")
print_error(f"Failed to handle the error: {str(e)}")

self.error_handling_in_progress.clear()
logger.info("Exiting handle_error method")

def default_error_handler(self, error_context, monitor):
logger.warning(
"Default error handler invoked. No specific fix available.")
print_warning(
"Default error handler invoked. No specific fix available.")
print_info(
"Please review the error and make necessary code changes manually.")

def request_restart(self):
self.restart_requested.set()

0 comments on commit 9243ade

Please sign in to comment.