diff --git a/agent_logwatch.py b/agent_logwatch.py index 6ccf8a1..9bb3c69 100644 --- a/agent_logwatch.py +++ b/agent_logwatch.py @@ -154,6 +154,7 @@ class LogWatchAgent(BaseAgent): INSERT OR IGNORE INTO agent_config VALUES ('max_overage_minutes', '30'); INSERT OR IGNORE INTO agent_config VALUES ('enabled', '1'); INSERT OR IGNORE INTO agent_config VALUES ('log_retention_days', '7'); + INSERT OR IGNORE INTO agent_config VALUES ('local_collect_time', ''); """) def _cfg(self, key: str, default: str = '') -> str: @@ -288,7 +289,7 @@ class LogWatchAgent(BaseAgent): """(Re)programme les jobs APScheduler selon la config DB.""" if not self._scheduler: return - for job_id in ('_slot_start', '_slot_end'): + for job_id in ('_slot_start', '_slot_end', '_local_collect'): try: self._scheduler.remove_job(job_id) except Exception: @@ -313,6 +314,20 @@ class LogWatchAgent(BaseAgent): self._scheduler.add_job( self._signal_slot_end, 'cron', hour=eh, minute=em, id='_slot_end' ) + + # Job de collecte locale (séparé, configurable indépendamment) + local_collect = self._cfg('local_collect_time', '') + if local_collect: + try: + lh, lm = map(int, local_collect.split(':')) + self._scheduler.add_job( + self._collect_local_logs, 'cron', + hour=lh, minute=lm, id='_local_collect' + ) + logger.info(f"Collecte locale programmée: {local_collect}") + except ValueError: + logger.error(f"Format local_collect_time invalide: {local_collect}") + logger.info(f"Analyse programmée: {start_str} → {end_str}") def _start_slot(self): @@ -324,9 +339,6 @@ class LogWatchAgent(BaseAgent): if self._slot_end_time <= now: self._slot_end_time += timedelta(days=1) - # Collecter les logs locaux avant de commencer l'analyse - self._collect_local_logs() - self._analysis_stop.clear() self._analysis_thread = threading.Thread( target=self._analysis_loop, daemon=True, name="logwatch-analysis" diff --git a/config/system_prompt.txt b/config/system_prompt.txt index a82015e..99fcc30 100644 --- a/config/system_prompt.txt +++ b/config/system_prompt.txt @@ -19,6 +19,8 @@ Tu reçois des instructions via MQTT (depuis Nexus) ou XMPP (directement). - `schedule show` : voir le créneau horaire configuré - `schedule set HH:MM-HH:MM` : définir le créneau d'analyse automatique - `schedule enable/disable` : activer/désactiver l'analyse automatique + - `schedule local HH:MM` : heure de collecte des logs locaux (machine hébergeant l'agent) + - `schedule local off` : désactiver la collecte locale automatique - `overage ` : définir le dépassement maximum autorisé - `retention ` : durée de conservation des logs filtrés - `analyze ` : lancer l'analyse d'une machine spécifique maintenant diff --git a/data/logwatch.db b/data/logwatch.db index 99064ed..087a83c 100644 Binary files a/data/logwatch.db and b/data/logwatch.db differ diff --git a/skills/__pycache__/logwatch.cpython-313.pyc b/skills/__pycache__/logwatch.cpython-313.pyc index feada4a..9b4ddba 100644 Binary files a/skills/__pycache__/logwatch.cpython-313.pyc and b/skills/__pycache__/logwatch.cpython-313.pyc differ diff --git a/skills/logwatch.py b/skills/logwatch.py index 36128ed..44439e4 100644 --- a/skills/logwatch.py +++ b/skills/logwatch.py @@ -116,6 +116,26 @@ def run(args: str, context) -> str: f"État : {'activé ✅' if enabled else 'désactivé ❌'}" ) + if sub == 'local': + # schedule local HH:MM — configurer l'heure de collecte locale + # schedule local off — désactiver + if not sub_rest: + val = _cfg(context, 'local_collect_time', '') + return f"Collecte locale : {val or 'désactivée'}" + if sub_rest.lower() == 'off': + _set_cfg(context, 'local_collect_time', '') + context.agent._reload_schedule() + return "✅ Collecte locale désactivée." + try: + lh, lm = map(int, sub_rest.split(':')) + if not (0 <= lh < 24 and 0 <= lm < 60): + return "Heure invalide." + except ValueError: + return "Format: schedule local HH:MM (ex: 01:00) ou off" + _set_cfg(context, 'local_collect_time', sub_rest.strip()) + context.agent._reload_schedule() + return f"✅ Collecte locale programmée à {sub_rest.strip()}." + if sub == 'set': # Format : HH:MM-HH:MM if '-' not in sub_rest: @@ -140,7 +160,7 @@ def run(args: str, context) -> str: context.agent._reload_schedule() return f"✅ Analyse automatique {'activée' if val=='1' else 'désactivée'}." - return "Sub-commande inconnue. Utilise : show, set , enable, disable" + return "Sub-commande inconnue. Utilise : show, set , enable, disable, local " # ── overage ─────────────────────────────────────────────────────────────── if action == 'overage':