Пример #1
0
    def divert_to_file(self, req: "CamcopsRequest") -> None:
        """
        Write an HL7 message to a file. For debugging.

        Args:
            req: a :class:`camcops_server.cc_modules.cc_request.CamcopsRequest`
        """
        exported_task = self.exported_task
        recipient = exported_task.recipient
        filename = recipient.get_filename(req,
                                          exported_task.task,
                                          override_task_format="hl7")
        now_utc = get_now_utc_pendulum()
        log.info("Diverting HL7 message to file {!r}", filename)
        written = exported_task.export_file(filename=filename,
                                            text=str(self._hl7_msg))
        if not written:
            return

        if recipient.hl7_debug_treat_diverted_as_sent:
            self.sent_at_utc = now_utc
            self.succeed(now_utc)
        else:
            self.abort("Exported to file as requested but not sent via HL7",
                       diverted_not_sent=True)
Пример #2
0
    def start(self, name: str, increment_count: bool = True) -> None:
        """
        Start a named timer.

        Args:
            name: name of the timer
            increment_count: increment the start count for this timer

        """
        if not self._timing:
            return
        now = get_now_utc_pendulum()

        # If we were already timing something else, pause that.
        if self._stack:
            last = self._stack[-1]
            self._totaldurations[last] += now - self._starttimes[last]

        # Start timing our new thing
        if name not in self._starttimes:
            self._totaldurations[name] = datetime.timedelta()
            self._count[name] = 0
        self._starttimes[name] = now
        if increment_count:
            self._count[name] += 1
        self._stack.append(name)
Пример #3
0
    def stop(self, name: str) -> None:
        """
        Stop a named timer.

        Args:
            name: timer to stop
        """
        if not self._timing:
            return
        now = get_now_utc_pendulum()

        # Validity check
        if not self._stack:
            raise AssertionError("MultiTimer.stop() when nothing running")
        if self._stack[-1] != name:
            raise AssertionError(f"MultiTimer.stop({name!r}) when "
                                 f"{self._stack[-1]!r} is running")

        # Finish what we were asked to
        self._totaldurations[name] += now - self._starttimes[name]
        self._stack.pop()

        # Now, if we were timing something else before we started "name",
        # resume...
        if self._stack:
            last = self._stack[-1]
            self._starttimes[last] = now
Пример #4
0
def nlprp_datetime_now(as_local: bool = True) -> str:
    """
    Returns the time now, as a string suitable for use with NLPRP.

    Args:
        as_local: use local timezone? (Otherwise, use UTC.)
    """
    now = get_now_localtz_pendulum() if as_local else get_now_utc_pendulum()
    return pendulum_to_nlprp_datetime(now)
Пример #5
0
 def reset(self) -> None:
     """
     Reset the timers.
     """
     self._overallstart = get_now_utc_pendulum()
     self._starttimes.clear()
     self._totaldurations.clear()
     self._count.clear()
     self._stack.clear()
Пример #6
0
 def __init__(self, start: bool = True) -> None:
     """
     Args:
         start: start the timer immediately?
     """
     self._timing = start
     self._overallstart = get_now_utc_pendulum()
     self._starttimes = OrderedDict()  # name: start time
     self._totaldurations = OrderedDict()  # name: duration
     self._count = OrderedDict()  # name: count
     self._stack = []  # list of names
Пример #7
0
    def report(self) -> None:
        """
        Finish and report to the log.
        """
        while self._stack:
            self.stop(self._stack[-1])
        now = get_now_utc_pendulum()
        grand_total = datetime.timedelta()
        overall_duration = now - self._overallstart
        for name, duration in self._totaldurations.items():
            grand_total += duration

        log.info("Timing summary:")
        summaries = []
        for name, duration in self._totaldurations.items():
            n = self._count[name]
            total_sec = duration.total_seconds()
            mean = total_sec / n if n > 0 else None

            summaries.append({
                'total':
                total_sec,
                'description': (
                    f"- {name}: {total_sec:.3f} s "
                    f"({(100 * total_sec / grand_total.total_seconds()):.2f}%, "  # noqa
                    f"n={n}, mean={mean:.3f}s)"),
            })
        summaries.sort(key=lambda x: x['total'], reverse=True)
        for s in summaries:
            # noinspection PyTypeChecker
            log.info(s["description"])
        if not self._totaldurations:
            log.info("<no timings recorded>")

        unmetered = overall_duration - grand_total
        log.info(
            "Unmetered time: {:.3f} s ({:.2f}%)", unmetered.total_seconds(),
            100 * unmetered.total_seconds() / overall_duration.total_seconds())
        log.info("Total time: {:.3f} s", grand_total.total_seconds())
Пример #8
0
    def send(self,
             host: str,
             username: str,
             password: str,
             port: int = None,
             use_tls: bool = True) -> bool:
        """
        Sends message and returns success.
        """
        if port is None:
            port = STANDARD_TLS_PORT if use_tls else STANDARD_SMTP_PORT

        msg = None
        msg_string = None
        if self.msg:
            msg = self.msg
        elif self.msg_string:
            msg_string = self.msg_string
        else:
            log.error("Can't send message; not present (not saved?)")
            return False

        if not password:
            log.error("Can't send message; password unknown")
            return False

        if self.sent:
            log.info("Resending message")

        self.host = host
        self.port = port
        self.username = username
        # don't save password
        self.use_tls = use_tls
        to_addrs = COMMASPACE.join(x for x in [self.to, self.cc, self.bcc]
                                   if x)
        header_components = filter(
            None,
            [
                "To: {}".format(self.to) if self.to else "",
                "Cc: {}".format(self.cc) if self.cc else "",
                "Bcc: {}".format(self.bcc) if self.bcc else "",  # noqa
                "Subject: {}".format(self.subject) if self.subject else "",
            ])
        log.info("Sending email -- {}", " -- ".join(header_components))
        try:
            send_msg(
                from_addr=self.from_addr,
                to_addrs=to_addrs,
                host=host,
                user=username,
                password=password,
                port=port,
                use_tls=use_tls,
                msg=msg,
                msg_string=msg_string,
            )
            log.debug("... sent")
            self.sent = True
            self.sent_at_utc = get_now_utc_pendulum()
            self.sending_failure_reason = None
        except RuntimeError as e:
            log.error("Failed to send e-mail: {!s}", e)
            if not self.sent:
                self.sent = False
                self.sending_failure_reason = str(e)