fix: pas de favoritisme pour la machine locale
- Retire _collect_local_logs() du démarrage du slot d'analyse - La machine locale passe par le même pipeline MQTT que les distantes - Nouveau job APScheduler indépendant: local_collect_time (config DB) - Commande: logwatch schedule local HH:MM / off Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+16
-4
@@ -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 ('max_overage_minutes', '30');
|
||||||
INSERT OR IGNORE INTO agent_config VALUES ('enabled', '1');
|
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 ('log_retention_days', '7');
|
||||||
|
INSERT OR IGNORE INTO agent_config VALUES ('local_collect_time', '');
|
||||||
""")
|
""")
|
||||||
|
|
||||||
def _cfg(self, key: str, default: str = '') -> str:
|
def _cfg(self, key: str, default: str = '') -> str:
|
||||||
@@ -288,7 +289,7 @@ class LogWatchAgent(BaseAgent):
|
|||||||
"""(Re)programme les jobs APScheduler selon la config DB."""
|
"""(Re)programme les jobs APScheduler selon la config DB."""
|
||||||
if not self._scheduler:
|
if not self._scheduler:
|
||||||
return
|
return
|
||||||
for job_id in ('_slot_start', '_slot_end'):
|
for job_id in ('_slot_start', '_slot_end', '_local_collect'):
|
||||||
try:
|
try:
|
||||||
self._scheduler.remove_job(job_id)
|
self._scheduler.remove_job(job_id)
|
||||||
except Exception:
|
except Exception:
|
||||||
@@ -313,6 +314,20 @@ class LogWatchAgent(BaseAgent):
|
|||||||
self._scheduler.add_job(
|
self._scheduler.add_job(
|
||||||
self._signal_slot_end, 'cron', hour=eh, minute=em, id='_slot_end'
|
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}")
|
logger.info(f"Analyse programmée: {start_str} → {end_str}")
|
||||||
|
|
||||||
def _start_slot(self):
|
def _start_slot(self):
|
||||||
@@ -324,9 +339,6 @@ class LogWatchAgent(BaseAgent):
|
|||||||
if self._slot_end_time <= now:
|
if self._slot_end_time <= now:
|
||||||
self._slot_end_time += timedelta(days=1)
|
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_stop.clear()
|
||||||
self._analysis_thread = threading.Thread(
|
self._analysis_thread = threading.Thread(
|
||||||
target=self._analysis_loop, daemon=True, name="logwatch-analysis"
|
target=self._analysis_loop, daemon=True, name="logwatch-analysis"
|
||||||
|
|||||||
@@ -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 show` : voir le créneau horaire configuré
|
||||||
- `schedule set HH:MM-HH:MM` : définir le créneau d'analyse automatique
|
- `schedule set HH:MM-HH:MM` : définir le créneau d'analyse automatique
|
||||||
- `schedule enable/disable` : activer/désactiver l'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 <minutes>` : définir le dépassement maximum autorisé
|
- `overage <minutes>` : définir le dépassement maximum autorisé
|
||||||
- `retention <jours>` : durée de conservation des logs filtrés
|
- `retention <jours>` : durée de conservation des logs filtrés
|
||||||
- `analyze <hostname>` : lancer l'analyse d'une machine spécifique maintenant
|
- `analyze <hostname>` : lancer l'analyse d'une machine spécifique maintenant
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
+21
-1
@@ -116,6 +116,26 @@ def run(args: str, context) -> str:
|
|||||||
f"État : {'activé ✅' if enabled else 'désactivé ❌'}"
|
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':
|
if sub == 'set':
|
||||||
# Format : HH:MM-HH:MM
|
# Format : HH:MM-HH:MM
|
||||||
if '-' not in sub_rest:
|
if '-' not in sub_rest:
|
||||||
@@ -140,7 +160,7 @@ def run(args: str, context) -> str:
|
|||||||
context.agent._reload_schedule()
|
context.agent._reload_schedule()
|
||||||
return f"✅ Analyse automatique {'activée' if val=='1' else 'désactivée'}."
|
return f"✅ Analyse automatique {'activée' if val=='1' else 'désactivée'}."
|
||||||
|
|
||||||
return "Sub-commande inconnue. Utilise : show, set <HH:MM-HH:MM>, enable, disable"
|
return "Sub-commande inconnue. Utilise : show, set <HH:MM-HH:MM>, enable, disable, local <HH:MM|off>"
|
||||||
|
|
||||||
# ── overage ───────────────────────────────────────────────────────────────
|
# ── overage ───────────────────────────────────────────────────────────────
|
||||||
if action == 'overage':
|
if action == 'overage':
|
||||||
|
|||||||
Reference in New Issue
Block a user