forked from rembo10/headphones
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlogger.py
More file actions
177 lines (131 loc) · 5.82 KB
/
logger.py
File metadata and controls
177 lines (131 loc) · 5.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# Author: Nic Wolfe <nic@wolfeden.ca>
# URL: http://code.google.com/p/sickbeard/
#
# This file is part of Sick Beard.
#
# Sick Beard is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Sick Beard is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Sick Beard. If not, see <http://www.gnu.org/licenses/>.
from __future__ import with_statement
import os
import threading
import headphones
import logging
# number of log files to keep
NUM_LOGS = 3
# log size in bytes
LOG_SIZE = 10000000 # 10 megs
ERROR = logging.ERROR
WARNING = logging.WARNING
MESSAGE = logging.INFO
DEBUG = logging.DEBUG
reverseNames = {u'ERROR': ERROR,
u'WARNING': WARNING,
u'INFO': MESSAGE,
u'DEBUG': DEBUG}
class SBRotatingLogHandler(object):
def __init__(self, log_file, num_files, num_bytes):
self.num_files = num_files
self.num_bytes = num_bytes
self.log_file = log_file
self.cur_handler = None
self.writes_since_check = 0
self.log_lock = threading.Lock()
def initLogging(self, consoleLogging=True):
self.log_file = os.path.join(headphones.LOG_DIR, self.log_file)
self.cur_handler = self._config_handler()
logging.getLogger('headphones').addHandler(self.cur_handler)
# define a Handler which writes INFO messages or higher to the sys.stderr
if consoleLogging:
console = logging.StreamHandler()
console.setLevel(logging.INFO)
# set a format which is simpler for console use
console.setFormatter(logging.Formatter('%(asctime)s %(levelname)s::%(message)s', '%H:%M:%S'))
# add the handler to the root logger
logging.getLogger('headphones').addHandler(console)
logging.getLogger('headphones').setLevel(logging.DEBUG)
def _config_handler(self):
"""
Configure a file handler to log at file_name and return it.
"""
file_handler = logging.FileHandler(self.log_file)
file_handler.setLevel(logging.DEBUG)
file_handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)-8s %(message)s', '%b-%d %H:%M:%S'))
return file_handler
def _log_file_name(self, i):
"""
Returns a numbered log file name depending on i. If i==0 it just uses logName, if not it appends
it to the extension (blah.log.3 for i == 3)
i: Log number to ues
"""
return self.log_file + ('.' + str(i) if i else '')
def _num_logs(self):
"""
Scans the log folder and figures out how many log files there are already on disk
Returns: The number of the last used file (eg. mylog.log.3 would return 3). If there are no logs it returns -1
"""
cur_log = 0
while os.path.isfile(self._log_file_name(cur_log)):
cur_log += 1
return cur_log - 1
def _rotate_logs(self):
sb_logger = logging.getLogger('headphones')
# delete the old handler
if self.cur_handler:
self.cur_handler.flush()
self.cur_handler.close()
sb_logger.removeHandler(self.cur_handler)
# rename or delete all the old log files
for i in range(self._num_logs(), -1, -1):
cur_file_name = self._log_file_name(i)
try:
if i >= NUM_LOGS:
os.remove(cur_file_name)
else:
os.rename(cur_file_name, self._log_file_name(i+1))
except WindowsError:
pass
# the new log handler will always be on the un-numbered .log file
new_file_handler = self._config_handler()
self.cur_handler = new_file_handler
sb_logger.addHandler(new_file_handler)
def log(self, toLog, logLevel=MESSAGE):
with self.log_lock:
# check the size and see if we need to rotate
if self.writes_since_check >= 10:
if os.path.isfile(self.log_file) and os.path.getsize(self.log_file) >= LOG_SIZE:
self._rotate_logs()
self.writes_since_check = 0
else:
self.writes_since_check += 1
meThread = threading.currentThread().getName()
message = meThread + u" :: " + toLog
out_line = message.encode('utf-8')
sb_logger = logging.getLogger('headphones')
try:
if logLevel == DEBUG:
sb_logger.debug(out_line)
elif logLevel == MESSAGE:
sb_logger.info(out_line)
elif logLevel == WARNING:
sb_logger.warning(out_line)
elif logLevel == ERROR:
sb_logger.error(out_line)
# add errors to the UI logger
#classes.ErrorViewer.add(classes.UIError(message))
else:
sb_logger.log(logLevel, out_line)
except ValueError:
pass
sb_log_instance = SBRotatingLogHandler('headphones.log', NUM_LOGS, LOG_SIZE)
def log(toLog, logLevel=MESSAGE):
sb_log_instance.log(toLog, logLevel)