Passed
Push — master ( 6e8656...9792e6 )
by Dean
05:08 queued 02:39
created

InterfaceMessages.add()   A

Complexity

Conditions 3

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 9.3211

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 18
ccs 1
cts 9
cp 0.1111
rs 9.4285
cc 3
crap 9.3211
1 1
from exception_wrappers import ExceptionWrapper
2 1
from six import add_metaclass
3 1
from sortedcontainers import SortedSet
4 1
import collections
5 1
import logging
6 1
import sys
7 1
import time
8
9 1
Record = collections.namedtuple('Record', 'level timestamp message')
10 1
log = logging.getLogger(__name__)
11
12
13 1
class InterfaceMessagesMeta(type):
14 1
    @property
15
    def critical(cls):
16 1
        return cls.severity >= logging.CRITICAL
17
18 1
    @property
19
    def message(cls):
20
        if not cls.records:
21
            return logging.NOTSET
22
23
        # Return the latest highest level/severity message
24
        return cls.records[-1].message
25
26 1
    @property
27
    def record(cls):
28
        if not cls.records:
29
            return None
30
31
        return cls.records[-1]
32
33 1
    @property
34
    def severity(cls):
35 1
        if not cls.records:
36 1
            return logging.NOTSET
37
38
        # Return the highest error level/severity
39
        return cls.records[-1].level
40
41
42 1
@add_metaclass(InterfaceMessagesMeta)
43 1
class InterfaceMessages(object):
44 1
    records = SortedSet()
45
46 1
    @classmethod
47
    def add(cls, level, message, *args):
48
        try:
49
            message = message % args
50
        except TypeError:
51
            log.warn('Unable to format string %r, with arguments: %r', message, args)
52
53
        # Append message to log file
54
        if level <= logging.CRITICAL:
55
            log.log(level, message)
56
        else:
57
            log.log(logging.CRITICAL, message)
58
59
        # Add interface message record
60
        cls.records.add(Record(
61
            level=level,
62
            timestamp=time.time(),
63
            message=message
64
        ))
65
66 1
    @classmethod
67 1
    def add_exception(cls, level, message, exc_info=None):
68
        if exc_info is None:
69
            exc_info = sys.exc_info()
70
71
        # Ensure message has been provided
72
        if not message:
73
            log.warn('Ignoring add_exception() call, no message was provided')
74
            return
75
76
        # Append message to log file
77
        log.log(level, message, exc_info=exc_info)
78
79
        # Add interface message record
80
        cls.records.add(Record(
81
            level=level,
82
            timestamp=time.time(),
83
            message=message
84
        ))
85
86 1
    @classmethod
87
    def bind(cls):
88
        ExceptionWrapper.on('exception', cls._on_exception)
89
90
        log.info('Bound to exception events')
91
92 1
    @classmethod
93
    def _on_exception(cls, source, message, exc_info):
0 ignored issues
show
Unused Code introduced by
The argument source seems to be unused.
Loading history...
94
        # Append error message
95
        InterfaceMessages.add_exception(logging.CRITICAL, message, exc_info)
96