mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
Keep track of 'parent' operation in operation loggers
This commit is contained in:
parent
d8be90165c
commit
63ff02be50
1 changed files with 52 additions and 0 deletions
|
@ -28,6 +28,7 @@ import os
|
|||
import re
|
||||
import yaml
|
||||
import collections
|
||||
import glob
|
||||
|
||||
from datetime import datetime
|
||||
from logging import FileHandler, getLogger, Formatter
|
||||
|
@ -350,6 +351,8 @@ class OperationLogger(object):
|
|||
This class record logs and metadata like context or start time/end time.
|
||||
"""
|
||||
|
||||
_instances = []
|
||||
|
||||
def __init__(self, operation, related_to=None, **kwargs):
|
||||
# TODO add a way to not save password on app installation
|
||||
self.operation = operation
|
||||
|
@ -360,6 +363,8 @@ class OperationLogger(object):
|
|||
self.logger = None
|
||||
self._name = None
|
||||
self.data_to_redact = []
|
||||
self.parent = self.parent_logger()
|
||||
self._instances.append(self)
|
||||
|
||||
for filename in ["/etc/yunohost/mysql", "/etc/yunohost/psql"]:
|
||||
if os.path.exists(filename):
|
||||
|
@ -370,6 +375,50 @@ class OperationLogger(object):
|
|||
if not os.path.exists(self.path):
|
||||
os.makedirs(self.path)
|
||||
|
||||
def parent_logger(self):
|
||||
|
||||
# If there are other operation logger instances
|
||||
for instance in reversed(self._instances):
|
||||
# Is one of these operation logger started but not yet done ?
|
||||
if instance.started_at is not None and instance.ended_at is None:
|
||||
# We are a child of the first one we found
|
||||
return instance.name
|
||||
|
||||
locks = read_file("/var/run/moulinette_yunohost.lock").strip().split("\n")
|
||||
# If we're the process with the lock, we're the root logger
|
||||
if locks == [] or str(os.getpid()) in locks:
|
||||
return None
|
||||
|
||||
# If we get here, we are in a yunohost command called by a yunohost
|
||||
# (maybe indirectly from an app script for example...)
|
||||
#
|
||||
# The strategy is :
|
||||
# 1. list 20 most recent log files
|
||||
# 2. iterate over the PID of parent processes
|
||||
# 3. see if parent process has some log file open (being actively
|
||||
# written in)
|
||||
# 4. if among those file, there's an operation log file, we use the id
|
||||
# of the most recent file
|
||||
|
||||
recent_operation_logs = sorted(glob.iglob("/var/log/yunohost/categories/operation/*.log"), key=os.path.getctime, reverse=True)[:20]
|
||||
|
||||
import psutil
|
||||
proc = psutil.Process().parent()
|
||||
while proc is not None:
|
||||
# We use proc.open_files() to list files opened / actively used by this proc
|
||||
# We only keep files matching a recent yunohost operation log
|
||||
active_logs = sorted([f.path for f in proc.open_files() if f.path in recent_operation_logs], key=os.path.getctime, reverse=True)
|
||||
if active_logs != []:
|
||||
# extra the log if from the full path
|
||||
return os.path.basename(active_logs[0])[:-4]
|
||||
else:
|
||||
proc = proc.parent()
|
||||
continue
|
||||
|
||||
# If nothing found, assume we're the root operation logger
|
||||
return None
|
||||
|
||||
|
||||
def start(self):
|
||||
"""
|
||||
Start to record logs that change the system
|
||||
|
@ -456,6 +505,7 @@ class OperationLogger(object):
|
|||
data = {
|
||||
'started_at': self.started_at,
|
||||
'operation': self.operation,
|
||||
'parent': self.parent,
|
||||
}
|
||||
if self.related_to is not None:
|
||||
data['related_to'] = self.related_to
|
||||
|
@ -491,8 +541,10 @@ class OperationLogger(object):
|
|||
self.ended_at = datetime.utcnow()
|
||||
self._error = error
|
||||
self._success = error is None
|
||||
|
||||
if self.logger is not None:
|
||||
self.logger.removeHandler(self.file_handler)
|
||||
self.file_handler.close()
|
||||
|
||||
is_api = msettings.get('interface') == 'api'
|
||||
desc = _get_description_from_name(self.name)
|
||||
|
|
Loading…
Add table
Reference in a new issue