feat: Implement daily log rotation
- Add logging to monitor_agent.py to replace print statements. - Configure TimedRotatingFileHandler to keep logs for the past 24 hours. - Update .gitignore to exclude the new log file. - Update PROGRESS.md to reflect the completion of the task.
This commit is contained in:
@@ -12,12 +12,26 @@ import os
|
||||
from datetime import datetime, timezone
|
||||
import pingparsing
|
||||
import nmap
|
||||
import logging
|
||||
from logging.handlers import TimedRotatingFileHandler
|
||||
|
||||
# Load configuration
|
||||
import config
|
||||
|
||||
from syslog_rfc5424_parser import parser
|
||||
|
||||
# --- Logging Configuration ---
|
||||
LOG_FILE = "monitoring_agent.log"
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
# Create a handler that rotates logs daily, keeping 1 backup
|
||||
handler = TimedRotatingFileHandler(LOG_FILE, when="midnight", interval=1, backupCount=1)
|
||||
handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
|
||||
|
||||
logger.addHandler(handler)
|
||||
|
||||
|
||||
LOG_POSITION_FILE = 'log_position.txt'
|
||||
AUTH_LOG_POSITION_FILE = 'auth_log_position.txt'
|
||||
|
||||
@@ -49,10 +63,10 @@ def get_system_logs():
|
||||
|
||||
return {"syslog": parsed_logs}
|
||||
except FileNotFoundError:
|
||||
print("Error: /var/log/syslog not found.")
|
||||
logger.error("/var/log/syslog not found.")
|
||||
return {"syslog": []}
|
||||
except Exception as e:
|
||||
print(f"Error reading syslog: {e}")
|
||||
logger.error(f"Error reading syslog: {e}")
|
||||
return {"syslog": []}
|
||||
|
||||
|
||||
@@ -66,7 +80,7 @@ def get_network_metrics():
|
||||
result = transmitter.ping()
|
||||
return ping_parser.parse(result).as_dict()
|
||||
except Exception as e:
|
||||
print(f"Error getting network metrics: {e}")
|
||||
logger.error(f"Error getting network metrics: {e}")
|
||||
return {"error": "ping command failed"}
|
||||
|
||||
def get_sensor_data():
|
||||
@@ -74,7 +88,7 @@ def get_sensor_data():
|
||||
try:
|
||||
return subprocess.check_output(["sensors"], text=True)
|
||||
except (subprocess.CalledProcessError, FileNotFoundError):
|
||||
print("Error: 'sensors' command not found. Please install lm-sensors.")
|
||||
logger.error("'sensors' command not found. Please install lm-sensors.")
|
||||
return None
|
||||
|
||||
def get_cpu_temperature(sensors_output):
|
||||
@@ -105,7 +119,6 @@ def get_gpu_temperature(sensors_output):
|
||||
return {"gpu_temperature": "N/A"}
|
||||
|
||||
|
||||
|
||||
def get_login_attempts():
|
||||
"""Gets system login attempts from /var/log/auth.log since the last check."""
|
||||
try:
|
||||
@@ -129,10 +142,10 @@ def get_login_attempts():
|
||||
|
||||
return {"failed_login_attempts": failed_logins}
|
||||
except FileNotFoundError:
|
||||
print("Error: /var/log/auth.log not found.")
|
||||
logger.error("/var/log/auth.log not found.")
|
||||
return {"failed_login_attempts": []}
|
||||
except Exception as e:
|
||||
print(f"Error reading login attempts: {e}")
|
||||
logger.error(f"Error reading login attempts: {e}")
|
||||
return {"failed_logins": []}
|
||||
|
||||
def get_nmap_scan_results():
|
||||
@@ -141,7 +154,7 @@ def get_nmap_scan_results():
|
||||
nm = nmap.PortScanner()
|
||||
scan_options = config.NMAP_SCAN_OPTIONS
|
||||
if os.geteuid() != 0 and "-sS" in scan_options:
|
||||
print("Warning: Nmap -sS scan requires root privileges. Falling back to -sT.")
|
||||
logger.warning("Nmap -sS scan requires root privileges. Falling back to -sT.")
|
||||
scan_options = scan_options.replace("-sS", "-sT")
|
||||
|
||||
scan_results = nm.scan(hosts=config.NMAP_TARGETS, arguments=scan_options)
|
||||
@@ -168,7 +181,7 @@ def get_nmap_scan_results():
|
||||
|
||||
return processed_results
|
||||
except Exception as e:
|
||||
print(f"Error performing Nmap scan: {e}")
|
||||
logger.error(f"Error performing Nmap scan: {e}")
|
||||
return {"error": "Nmap scan failed"}
|
||||
|
||||
# --- LLM Interaction Function ---
|
||||
@@ -247,15 +260,15 @@ def analyze_data_with_llm(data, baselines):
|
||||
return json.loads(json_string)
|
||||
else:
|
||||
# Handle cases where the response is not valid JSON
|
||||
print(f"LLM returned a non-JSON response: {sanitized_response}")
|
||||
logger.warning(f"LLM returned a non-JSON response: {sanitized_response}")
|
||||
return {"severity": "low", "reason": sanitized_response}
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"Error decoding LLM response: {e}")
|
||||
logger.error(f"Error decoding LLM response: {e}")
|
||||
# Fallback for invalid JSON
|
||||
return {"severity": "low", "reason": sanitized_response}
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error interacting with LLM: {e}")
|
||||
logger.error(f"Error interacting with LLM: {e}")
|
||||
return None
|
||||
|
||||
|
||||
@@ -267,11 +280,11 @@ def send_discord_alert(message):
|
||||
try:
|
||||
response = webhook.execute()
|
||||
if response.status_code == 200:
|
||||
print("Discord alert sent successfully.")
|
||||
logger.info("Discord alert sent successfully.")
|
||||
else:
|
||||
print(f"Error sending Discord alert: {response.status_code} - {response.content}")
|
||||
logger.error(f"Error sending Discord alert: {response.status_code} - {response.content}")
|
||||
except Exception as e:
|
||||
print(f"Error sending Discord alert: {e}")
|
||||
logger.error(f"Error sending Discord alert: {e}")
|
||||
|
||||
def send_google_home_alert(message):
|
||||
"""Sends an alert to a Google Home speaker via Home Assistant."""
|
||||
@@ -280,7 +293,7 @@ def send_google_home_alert(message):
|
||||
response = ollama.generate(model="llama3.1:8b", prompt=f"Summarize the following message in a single sentence: {message}")
|
||||
simplified_message = response['response'].strip()
|
||||
except Exception as e:
|
||||
print(f"Error summarizing message: {e}")
|
||||
logger.error(f"Error summarizing message: {e}")
|
||||
simplified_message = message.split('.')[0] # Take the first sentence as a fallback
|
||||
|
||||
url = f"{config.HOME_ASSISTANT_URL}/api/services/tts/speak"
|
||||
@@ -296,11 +309,11 @@ def send_google_home_alert(message):
|
||||
try:
|
||||
response = requests.post(url, headers=headers, json=data)
|
||||
if response.status_code == 200:
|
||||
print("Google Home alert sent successfully.")
|
||||
logger.info("Google Home alert sent successfully.")
|
||||
else:
|
||||
print(f"Error sending Google Home alert: {response.status_code} - {response.text}")
|
||||
logger.error(f"Error sending Google Home alert: {response.status_code} - {response.text}")
|
||||
except Exception as e:
|
||||
print(f"Error sending Google Home alert: {e}")
|
||||
logger.error(f"Error sending Google Home alert: {e}")
|
||||
|
||||
# --- Main Script Logic ---
|
||||
|
||||
@@ -308,7 +321,7 @@ daily_events = []
|
||||
|
||||
def run_monitoring_cycle(nmap_scan_counter):
|
||||
"""Runs a single monitoring cycle."""
|
||||
print("Running monitoring cycle...")
|
||||
logger.info("Running monitoring cycle...")
|
||||
system_logs = get_system_logs()
|
||||
network_metrics = get_network_metrics()
|
||||
sensors_output = get_sensor_data()
|
||||
@@ -349,7 +362,7 @@ def run_monitoring_cycle(nmap_scan_counter):
|
||||
def main():
|
||||
"""Main function to run the monitoring agent."""
|
||||
if config.TEST_MODE:
|
||||
print("Running in test mode...")
|
||||
logger.info("Running in test mode...")
|
||||
run_monitoring_cycle(0)
|
||||
else:
|
||||
nmap_scan_counter = 0
|
||||
@@ -366,8 +379,4 @@ def main():
|
||||
time.sleep(300) # Run every 5 minutes
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
|
||||
|
||||
|
||||
main()
|
||||
Reference in New Issue
Block a user