Test Failed
Push — develop ( 2f2c0e...2adb06 )
by Dean
02:41
created

LoggerManager.setup()   A

Complexity

Conditions 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6
Metric Value
cc 2
dl 0
loc 8
rs 9.4285
ccs 0
cts 3
cp 0
crap 6
1
from plugin.core.constants import PLUGIN_IDENTIFIER
2
from plugin.core.environment import Environment
3
from plugin.core.helpers.variable import md5
4
from plugin.core.logger.filters import FrameworkFilter, AuthorizationFilter, RequestsFilter
5
6
from logging.handlers import RotatingFileHandler
7
import logging
8
9
LOG_FORMAT = '%(asctime)-15s - %(name)-32s (%(thread)x) :  %(levelname)s (%(name)s:%(lineno)d) - %(message)s'
10
LOG_OPTIONS = {
11
    'plex':                         'libraries',
12
    'plex_activity':                'libraries',
13
    'plex_metadata':                'libraries',
14
    'raven':                        'libraries',
15
    'requests':                     'libraries',
16
    'trakt':                        'libraries',
17
18
    'peewee':                       'peewee',
19
    'peewee_migrate':               'peewee',
20
21
    'com.plexapp.plugins.trakttv':  'plugin',
22
    'plugin':                       'plugin',
23
24
    'pyemitter':                    'pyemitter'
25
}
26
27
TRACE = 5
28
29
log = logging.getLogger(__name__)
30
31
32
class LogHandler(logging.Handler):
33
    def __init__(self, handler):
34
        super(LogHandler, self).__init__()
35
36
        self.handler = handler
37
38
        # Update formatter for log file
39
        self.handler.formatter._fmt = LOG_FORMAT
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like _fmt was declared protected and should not be accessed from this context.

Prefixing a member variable _ is usually regarded as the equivalent of declaring it with protected visibility that exists in other languages. Consequentially, such a member should only be accessed from the same class or a child class:

class MyParent:
    def __init__(self):
        self._x = 1;
        self.y = 2;

class MyChild(MyParent):
    def some_method(self):
        return self._x    # Ok, since accessed from a child class

class AnotherClass:
    def some_method(self, instance_of_my_child):
        return instance_of_my_child._x   # Would be flagged as AnotherClass is not
                                         # a child class of MyParent
Loading history...
40
41
    @property
42
    def baseFilename(self):
43
        return self.handler.baseFilename
44
45
    def emit(self, record):
46
        return self.handler.emit(record)
47
48
49
class LoggerManager(object):
50
    @staticmethod
51
    def get_handler():
52
        logger = logging.getLogger(PLUGIN_IDENTIFIER)
53
54
        for h in logger.handlers:
55
            if type(h) is RotatingFileHandler:
56
                logger.handlers.remove(h)
57
                return LogHandler(h)
58
59
        return None
60
61
    @classmethod
62
    def setup(cls, report=True, storage=True):
63
        cls.setup_logging(report, storage)
64
65
        if report:
66
            cls.setup_raven()
67
68
        log.debug('Initialized logging (report: %r, storage: %r)', report, storage)
69
70
    @staticmethod
71
    def setup_logging(report=True, storage=True):
72
        # Setup root logger
73
        rootLogger = logging.getLogger()
74
75
        # Set filters
76
        rootLogger.filters = [
77
            FrameworkFilter()
78
        ]
79
80
        # Set level
81
        rootLogger.setLevel(logging.DEBUG)
82
83
        # Set handlers
84
        rootLogger.handlers = [
85
            LOG_HANDLER
86
        ]
87
88
        # Setup error reporting (if enabled)
89
        if report:
90
            from plugin.core.logger.handlers.error_reporter import ERROR_REPORTER_HANDLER
91
92
            rootLogger.handlers.append(ERROR_REPORTER_HANDLER)
93
94
        # Setup local error storage (if enabled)
95
        if storage:
96
            from plugin.core.logger.handlers.error_storage import ERROR_STORAGE_HANDLER
97
98
            rootLogger.handlers.append(ERROR_STORAGE_HANDLER)
99
100
    @staticmethod
101
    def setup_raven():
102
        from plugin.core.logger.handlers.error_reporter import RAVEN
103
104
        # Set client name to a hash of `machine_identifier`
105
        RAVEN.name = md5(Environment.platform.machine_identifier)
106
107
        RAVEN.tags.update({
108
            'server.version': Environment.platform.server_version
109
        })
110
111
    @classmethod
112
    def refresh(cls):
113
        for name, option in LOG_OPTIONS.items():
114
            logger = logging.getLogger(name)
115
116
            # Retrieve logger level, check if it has changed
117
            level = cls.get_level(option)
118
119
            if level == logger.level:
120
                continue
121
122
            # Update logger level
123
            log.debug('Changed %r logger level to %s', name, logging.getLevelName(level))
124
125
            logger.setLevel(level)
126
127
    @staticmethod
128
    def get_level(option):
129
        # Try retrieve preference
130
        try:
131
            value = Environment.prefs['level_%s' % option]
132
        except KeyError:
133
            # Default to "plugin" preference
134
            value = Environment.prefs['level_plugin']
135
136
        # Parse labels into level attributes
137
        if value == 'ERROR':
138
            return logging.ERROR
139
140
        if value == 'WARN' or value == 'WARNING':
141
            return logging.WARNING
142
143
        if value == 'INFO':
144
            return logging.INFO
145
146
        if value == 'DEBUG':
147
            return logging.DEBUG
148
149
        if value == "TRACE":
150
            return TRACE
151
152
        log.warn('Unknown logging level "%s"', value)
153
        return logging.DEBUG
154
155
# Get the logging file handler
156
LOG_HANDLER = LoggerManager.get_handler()
157
LOG_HANDLER.addFilter(AuthorizationFilter())
158
LOG_HANDLER.addFilter(RequestsFilter())
159