Commit 63c04920 authored by Joel Collins's avatar Joel Collins
Browse files

Added route to download logfile

parent d54a35e1
Loading
Loading
Loading
Loading
+33 −8
Original line number Diff line number Diff line
#!/usr/bin/env python

from flask import (
    Flask, render_template, jsonify)
    Flask, render_template, jsonify, send_file)

from flask.logging import default_handler
from serial import SerialException
from datetime import datetime

from flask_cors import CORS

@@ -16,6 +17,8 @@ from openflexure_microscope.camera.pi import StreamingCamera
from openflexure_microscope.stage.sanga import SangaStage
from openflexure_microscope.stage.mock import MockStage

from openflexure_microscope.config import USER_CONFIG_DIR

import atexit
import logging
import sys, os
@@ -23,20 +26,34 @@ import sys, os
# Handle logging
is_gunicorn = "gunicorn" in os.environ.get("SERVER_SOFTWARE", "")

DEFAULT_LOGFILE = os.path.join(USER_CONFIG_DIR, 'openflexure_microscope.log')
print(DEFAULT_LOGFILE)

if (__name__ == "__main__") or (not is_gunicorn):
    # If imported, but not by gunicorn
    print("Letting sys handle logs")
    logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
else:
    print("Letting gunicorn handle logs")
    # If running in gunicorn, let gunicorn handle logging
    # Direct standard Python logging to file and console
    root = logging.getLogger()
    error_formatter = logging.Formatter("[%(asctime)s] [%(threadName)s] [%(levelname)s] %(message)s")

    rotating_logfile = logging.handlers.RotatingFileHandler(
        DEFAULT_LOGFILE, 
        maxBytes=1000000, 
        backupCount=7
    )

    gunicorn_logger = logging.getLogger('gunicorn.error')
    for handler in gunicorn_logger.handlers:
    error_handlers = [
        rotating_logfile,
        logging.StreamHandler()
    ]

    for handler in error_handlers:
        handler.setFormatter(error_formatter)
        root.addHandler(handler)

    root.setLevel(gunicorn_logger.level)
    root.setLevel(logging.getLogger("gunicorn.error").level)

# Create a dummy microscope object, with no hardware attachments
api_microscope = Microscope(None, None)
@@ -119,6 +136,14 @@ def routes():
    """
    return jsonify(list_routes(app))

@app.route('/log')
def err_log():
    """
    Most recent 1mb of log output
    """
    timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
    return send_file(DEFAULT_LOGFILE, as_attachment=True, attachment_filename='openflexure_microscope_{}.log'.format(timestamp))

# Automatically clean up microscope at exit
def cleanup():
    global api_microscope
+0 −27
Original line number Diff line number Diff line
from openflexure_stage import OpenFlexureStage

from openflexure_microscope.lock import StrictLock

import logging


class Stage(OpenFlexureStage):
    def __init__(self, *args, **kwargs):
        """
        Subclass of :py:class:`openflexure_stage.stage.OpenFlexureStage`, 
        adding an instance of :py:class:`openflexure_microscope.lock.StrictLock` to regulate access.
        """
        self.lock = StrictLock(timeout=2)  #: :py:class:`openflexure_microscope.lock.StrictLock`: Strict lock controlling thread access to camera hardware

        OpenFlexureStage.__init__(self, *args, **kwargs)

    
    def _move_rel_nobacklash(self, *args, **kwargs):
        """
        Overrides :py:function:`openflexure_stage.stage.OpenFlexureStage._move_rel_nobacklash` to acquire lock first.
        """
        if self._ser:
            with self.lock:
                OpenFlexureStage._move_rel_nobacklash(self, *args, **kwargs)
        else:
            logging.warning("Unable to move stage. Serial communication unavailable.")