V1.0.1
This commit is contained in:
@@ -30,12 +30,15 @@ def _read_log_file(filepath):
|
||||
return None
|
||||
|
||||
|
||||
_DATE_IN_NAME_RE = re.compile(r'_\d{2}-\d{2}-\d{2}[_.]')
|
||||
|
||||
|
||||
def _log_files_for_date(log_path, prefix, date_str):
|
||||
"""Retourne les fichiers de logs pour un prefixe et une date donnes, tries par index.
|
||||
|
||||
Essai 1 : fichiers avec la date dans le nom (ex: awevents_26-04-13_1.log).
|
||||
Essai 2 : si aucun fichier trouve, cherche sans date dans le nom et filtre
|
||||
par date de modification du fichier (ex: serveur HDS).
|
||||
Cherche les fichiers avec la date dans le nom (ex: awevents_26-04-13_1.log.gz).
|
||||
Pour le jour courant uniquement, inclut aussi les fichiers sans date dans le nom
|
||||
(ex: awevents.log, isoft.log) qui sont les logs actifs du jour.
|
||||
"""
|
||||
def is_valid(f):
|
||||
return f.endswith('.log') or f.endswith('.log.gz')
|
||||
@@ -44,29 +47,19 @@ def _log_files_for_date(log_path, prefix, date_str):
|
||||
m = re.search(r'_(\d+)\.log(\.gz)?$', f)
|
||||
return int(m.group(1)) if m else 0
|
||||
|
||||
# Essai 1 : date dans le nom
|
||||
# Fichiers avec la date dans le nom
|
||||
pattern = os.path.join(log_path, f"{prefix}_{date_str}_*")
|
||||
files = [f for f in glob.glob(pattern) if is_valid(f)]
|
||||
if files:
|
||||
return sorted(files, key=sort_key)
|
||||
|
||||
# Essai 2 : sans date dans le nom, filtrer par date de modification
|
||||
try:
|
||||
target_date = datetime.strptime(date_str, "%y-%m-%d").date()
|
||||
except ValueError:
|
||||
return []
|
||||
|
||||
fallback_pattern = os.path.join(log_path, f"{prefix}_*")
|
||||
files = []
|
||||
for f in glob.glob(fallback_pattern):
|
||||
if not is_valid(f):
|
||||
continue
|
||||
try:
|
||||
mtime = os.path.getmtime(f)
|
||||
if datetime.fromtimestamp(mtime).date() == target_date:
|
||||
# Pour le jour courant uniquement : inclure aussi les fichiers sans date dans le nom
|
||||
today_str = datetime.now().strftime("%y-%m-%d")
|
||||
if date_str == today_str:
|
||||
active_pattern = os.path.join(log_path, f"{prefix}*")
|
||||
for f in glob.glob(active_pattern):
|
||||
fname = os.path.basename(f)
|
||||
if is_valid(f) and not _DATE_IN_NAME_RE.search(fname) and f not in files:
|
||||
files.append(f)
|
||||
except OSError:
|
||||
continue
|
||||
|
||||
return sorted(files, key=sort_key)
|
||||
|
||||
|
||||
@@ -153,7 +146,10 @@ class UserMonitor:
|
||||
|
||||
status_order = {"actif": 0, "inactif": 1, "deconnecte": 2}
|
||||
sorted_users = dict(
|
||||
sorted(users.items(), key=lambda x: status_order.get(x[1]["status"], 3))
|
||||
sorted(users.items(), key=lambda x: (
|
||||
status_order.get(x[1]["status"], 3),
|
||||
-(x[1]["last_action_time"].timestamp() if x[1].get("last_action_time") else 0),
|
||||
))
|
||||
)
|
||||
hourly_data = [{"hour": h, "count": len(logins)} for h, logins in sorted(hourly.items())]
|
||||
|
||||
@@ -236,6 +232,49 @@ class UserMonitor:
|
||||
else:
|
||||
user["status"] = "actif"
|
||||
|
||||
def get_users_for_date(self, date):
|
||||
"""Retourne la liste des utilisateurs ayant agi a une date donnee, tries par nb d'actions."""
|
||||
log_path = self.config.get(
|
||||
"amadea_log_path",
|
||||
r"C:\ProgramData\ISoft\Amadea Web 8 x64\data\logs"
|
||||
)
|
||||
if not os.path.isdir(log_path):
|
||||
return []
|
||||
|
||||
date_str = date.strftime("%y-%m-%d")
|
||||
cutoff = datetime(date.year, date.month, date.day)
|
||||
files = _log_files_for_date(log_path, "awevents", date_str)
|
||||
if not files:
|
||||
return []
|
||||
|
||||
users = {}
|
||||
hourly = {h: set() for h in range(24)}
|
||||
for filepath in files:
|
||||
content = _read_log_file(filepath)
|
||||
if content:
|
||||
for line in content.splitlines():
|
||||
self._parse_awevents_line(line, users, cutoff, hourly)
|
||||
|
||||
result = sorted(users.values(), key=lambda u: -u.get("action_count_24h", 0))
|
||||
output = []
|
||||
for u in result:
|
||||
duration = None
|
||||
if u.get("connected_since") and u.get("last_action_time"):
|
||||
mins = int((u["last_action_time"] - u["connected_since"]).total_seconds() / 60)
|
||||
if mins >= 60:
|
||||
duration = f"{mins // 60}h{mins % 60:02d}"
|
||||
else:
|
||||
duration = f"{mins}min"
|
||||
output.append({
|
||||
"login": u["login"],
|
||||
"last_action_time": u["last_action_time"].strftime("%H:%M:%S") if u.get("last_action_time") else None,
|
||||
"last_action_label": u.get("last_action_label", ""),
|
||||
"action_count": u.get("action_count_24h", 0),
|
||||
"first_action_time": u["connected_since"].strftime("%H:%M") if u.get("connected_since") else None,
|
||||
"duration": duration,
|
||||
})
|
||||
return output
|
||||
|
||||
def get_weekly_activity(self):
|
||||
"""Retourne le nombre max d'utilisateurs actifs simultanes par jour (7 derniers jours)."""
|
||||
log_path = self.config.get(
|
||||
|
||||
Reference in New Issue
Block a user