# HG changeset patch # User Ludovic Chabant # Date 1454651418 28800 # Node ID cbb170d9c894571504a71e5211ebe0f91dfba209 # Parent a2d9ef307a089888a8856bd495dcb9e9b1c25399 admin: Improve publish logs showing as alerts in the admin panel. * Don't show stuff that happened before the page was opened. * Skinning tweaks. diff -r a2d9ef307a08 -r cbb170d9c894 foodtruck/pubutil.py --- a/foodtruck/pubutil.py Thu Feb 04 21:49:15 2016 -0800 +++ b/foodtruck/pubutil.py Thu Feb 04 21:50:18 2016 -0800 @@ -28,7 +28,20 @@ lambda *args: _shutdown_server_and_raise_sigint()) +def _read_pid_file(pid_file): + logger.debug("Reading PID file: %s" % pid_file) + try: + with open(pid_file, 'r') as fp: + pid_str = fp.read() + + return int(pid_str.strip()) + except Exception: + logger.error("Error reading PID file.") + raise + + def _pid_exists(pid): + logger.debug("Checking if process ID %d is running" % pid) try: os.kill(pid, 0) except OSError as ex: @@ -44,61 +57,52 @@ return True -def _read_pid_file(pid_file): - logger.debug("Reading PID file: %s" % pid_file) - try: - with open(pid_file, 'r') as fp: - pid_str = fp.read() - - return int(pid_str.strip()) - except Exception: - logger.error("Error reading PID file.") - raise - - class PublishLogReader(object): - _pub_max_time = 10 * 60 # Don't bother about pubs older than 10mins. _poll_interval = 1 # Check the process every 1 seconds. _ping_interval = 30 # Send a ping message every 30 seconds. def __init__(self, pid_path, log_path): self.pid_path = pid_path self.log_path = log_path - self._pub_pid_mtime = 0 - self._last_seek = -1 - self._last_ping_time = 0 def run(self): logger.debug("Opening publish log...") pid = None + pid_mtime = 0 is_running = False + last_seek = -1 + last_ping_time = 0 try: while not server_shutdown: # PING! - interval = time.time() - self._last_ping_time + interval = time.time() - last_ping_time if interval > self._ping_interval: logger.debug("Sending ping...") - self._last_ping_time = time.time() + last_ping_time = time.time() yield bytes("event: ping\ndata: 1\n\n", 'utf8') - # Check if the PID file has changed. + # Check the PID file timestamp. try: new_mtime = os.path.getmtime(self.pid_path) except OSError: new_mtime = 0 - if (new_mtime > 0 and - time.time() - new_mtime > self._pub_max_time): - new_mtime = 0 + # If there's a valid PID file and we either just started + # streaming (pid_mtime == 0) or we remember an older version + # of that PID file (pid_mtime != new_mtime), let's read the + # PID from the file. + is_pid_file_prehistoric = False + if new_mtime > 0 and new_mtime != pid_mtime: + is_pid_file_prehistoric = (pid_mtime == 0) + pid_mtime = new_mtime + pid = _read_pid_file(self.pid_path) - # Re-read the PID file. - prev_mtime = self._pub_pid_mtime - if new_mtime > 0 and new_mtime != prev_mtime: - self._pub_pid_mtime = new_mtime - pid = _read_pid_file(self.pid_path) - if pid: - logger.debug("Monitoring new process, PID: %d" % pid) + if is_pid_file_prehistoric: + logger.debug("PID file is pre-historic, we will skip the " + "first parts of the log.") + # If we have a valid PID, let's check if the process is + # currently running. was_running = is_running if pid: is_running = _pid_exists(pid) @@ -106,29 +110,41 @@ "Process %d is %s" % (pid, 'running' if is_running else 'not running')) if not is_running: + # Let's forget this PID file until it changes. pid = None else: is_running = False - # Send data. + # Read new data from the log file. new_data = None if is_running or was_running: - if self._last_seek < 0: - outstr = 'event: message\ndata: Publish started.\n\n' - yield bytes(outstr, 'utf8') - self._last_seek = 0 + if last_seek < 0: + # Only send the "publish started" message if we + # actually caught the process as it was starting, not + # if we started streaming after it started. + # This means we saw the PID file get changed. + if not is_pid_file_prehistoric: + outstr = ( + 'event: message\n' + 'data: Publish started.\n\n') + yield bytes(outstr, 'utf8') + last_seek = 0 try: with open(self.log_path, 'r', encoding='utf8') as fp: - fp.seek(self._last_seek) + fp.seek(last_seek) new_data = fp.read() - self._last_seek = fp.tell() + last_seek = fp.tell() except OSError: pass if not is_running: - self._last_seek = 0 + # Process is not running anymore, let's reset our seek + # marker back to the beginning. + last_seek = -1 - if new_data: + # Stream the new data to the client, but don't send old stuff + # that happened before we started this stream. + if new_data and not is_pid_file_prehistoric: logger.debug("SSE: %s" % new_data) for line in new_data.split('\n'): outstr = 'event: message\ndata: %s\n\n' % line diff -r a2d9ef307a08 -r cbb170d9c894 foodtruck/templates/layouts/master.html --- a/foodtruck/templates/layouts/master.html Thu Feb 04 21:49:15 2016 -0800 +++ b/foodtruck/templates/layouts/master.html Thu Feb 04 21:50:18 2016 -0800 @@ -21,7 +21,12 @@ {% block content %}{% endblock %} {% block after_content %}{% endblock %} -
+