Example #1
0
 def __init__(
     self,
     api_url,
     api_version,
     tool_name,
     tool_version,
     auth_token=None,
     log_level_system=6,
     log_level_user=5,
     enabled=True,
 ):
     self.api_url = api_url
     self.logs_url = urlparse.urljoin(api_url, "logs")
     self.api_version = api_version
     self.tool_name = tool_name
     self.tool_version = tool_version
     self.log_level_system = log_level_system
     self.log_level_user = log_level_user
     self.enabled = enabled
     self.setup_log_levels()
     if enabled:
         self.request_manager = RequestManager(auth_token=auth_token)
         self.request_manager.start()
     super(MemexLogHandler, self).__init__()
Example #2
0
class MemexLogHandler(logging.Handler):
    """Logging handler to use with Memex Artifact Storage API

    For more details, please see: http://docs.memexapi.apiary.io/
    """

    log = logging.getLogger("memex_logging.MemexLogHandler")
    _are_log_levels_set_up = False

    def __init__(
        self,
        api_url,
        api_version,
        tool_name,
        tool_version,
        auth_token=None,
        log_level_system=6,
        log_level_user=5,
        enabled=True,
    ):
        self.api_url = api_url
        self.logs_url = urlparse.urljoin(api_url, "logs")
        self.api_version = api_version
        self.tool_name = tool_name
        self.tool_version = tool_version
        self.log_level_system = log_level_system
        self.log_level_user = log_level_user
        self.enabled = enabled
        self.setup_log_levels()
        if enabled:
            self.request_manager = RequestManager(auth_token=auth_token)
            self.request_manager.start()
        super(MemexLogHandler, self).__init__()

    def emit(self, record):
        if self.enabled:
            if record.levelno in (self.log_level_system, self.log_level_user):
                document = self.to_document(record)
                self.send(document)

    def setup_log_levels(self):
        """Patch logging module to expose additional log level methods:
        system(), user() that receive well defined keyword arguments
        """
        if self._are_log_levels_set_up:
            return

        def log(
            self_,
            description,
            level_no,
            type,
            privacy="public",
            inferred=False,
            workflow=None,
            activity=None,
            user_id=None,
            session_id=None,
            details=None,
            attribute_indexes=None,
            controls=None,
        ):
            extra = {
                "description": description,
                "type": type,
                "inferred": inferred,
                "privacy": privacy,
                "workflow": workflow,
                "activity": activity,
                "user_id": user_id,
                "session_id": session_id,
                "details": details,
                "attribute_indexes": attribute_indexes,
                "controls": controls,
            }
            self_._log(level_no, description, None, extra=extra)

        def log_system(self_, *args, **kwargs):
            return log(self_, level_no=self.log_level_system, type="SYSTEM", *args, **kwargs)

        def log_user(self_, *args, **kwargs):
            return log(self_, level_no=self.log_level_user, type="USER", *args, **kwargs)

        logging.addLevelName(self.log_level_system, "SYSTEM")
        logging.Logger.system = log_system
        logging.addLevelName(self.log_level_user, "USER")
        logging.Logger.user = log_user
        self._are_log_levels_set_up = True

    def to_document(self, record):
        document = {
            "key": str(uuid.uuid4()),
            "time": {"startedAt": int(calendar.timegm(time.gmtime()) * 1000)},
            "action": {"type": record.type, "description": record.msg, "inferred": record.inferred},
            "client": {"ipAddress": self.get_public_ip(), "userAgent": self.get_user_agent()},
            "component": {
                "name": self.tool_name,
                "version": self.tool_version,
                "apiLanguage": "Python",
                "apiVersion": self.api_version,
            },
            "acl": {"privacy": record.privacy},
        }
        # Fill optional fields if provided
        if record.workflow is not None:
            document["action"]["workflow"] = record.workflow
        if record.activity is not None:
            document["action"]["activity"] = record.activity

        if record.user_id is not None:
            document["client"]["userId"] = record.user_id
        if record.session_id is not None:
            document["client"]["sessionId"] = record.session_id

        if record.details is not None:
            document["details"] = record.details
        if record.attribute_indexes is not None:
            document["attribute_indexes"] = record.attribute_indexes

        if record.privacy == "controlled":
            document["acl"]["controls"] = record.controls

        return document

    def send(self, document):
        try:
            data = json.dumps(document)
        except Exception as exc:
            self.log.error(exc)
            return

        request_kwargs = {
            "method": "POST",
            "url": self.logs_url,
            "headers": {"Content-Type": "application/json"},
            "data": data,
            "timeout": 5,
        }
        self.request_manager.add_request(**request_kwargs)

    def get_public_ip(self):
        if not hasattr(self, "_public_ip"):
            # TODO: Maybe there is another way to do it?
            ip = requests.get("http://httpbin.org/ip").json()["origin"]
            self._public_ip = ip
        return self._public_ip

    def get_user_agent(self):
        if not hasattr(self, "_user_agent"):
            self._user_agent = default_user_agent()
        return self._user_agent