diff options
Diffstat (limited to 'lib/dodai/config/log.py')
-rw-r--r-- | lib/dodai/config/log.py | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/lib/dodai/config/log.py b/lib/dodai/config/log.py new file mode 100644 index 0000000..fdb5c93 --- /dev/null +++ b/lib/dodai/config/log.py | |||
@@ -0,0 +1,150 @@ | |||
1 | # Copyright (C) 2010 Leonard Thomas | ||
2 | # | ||
3 | # This file is part of Dodai. | ||
4 | # | ||
5 | # Dodai is free software: you can redistribute it and/or modify | ||
6 | # it under the terms of the GNU General Public License as published by | ||
7 | # the Free Software Foundation, either version 3 of the License, or | ||
8 | # (at your option) any later version. | ||
9 | # | ||
10 | # Dodai is distributed in the hope that it will be useful, | ||
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | # GNU General Public License for more details. | ||
14 | # | ||
15 | # You should have received a copy of the GNU General Public License | ||
16 | # along with Dodai. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | |||
19 | import logging | ||
20 | import logging.handlers | ||
21 | import os | ||
22 | |||
23 | class ConfigLog(object): | ||
24 | |||
25 | LEVELS = { | ||
26 | logging.CRITICAL: [ | ||
27 | 'critical', | ||
28 | "%(asctime)s - %(name)s - %(levelname)s - %(message)s", | ||
29 | "%(message)s"], | ||
30 | logging.ERROR: [ | ||
31 | 'error', | ||
32 | "%(asctime)s - %(name)s - %(levelname)s - %(message)s", | ||
33 | "%(message)s"], | ||
34 | logging.WARNING: [ | ||
35 | 'warning', | ||
36 | "%(asctime)s - %(name)s - %(levelname)s - %(message)s", | ||
37 | "%(message)s"], | ||
38 | logging.INFO: [ | ||
39 | 'info', | ||
40 | "%(asctime)s - %(name)s - %(levelname)s - %(message)s", | ||
41 | "%(message)s"], | ||
42 | logging.DEBUG: [ | ||
43 | 'debug', | ||
44 | "%(asctime)s - %(name)s - %(levelname)s - %(message)s", | ||
45 | "%(message)s"] | ||
46 | } | ||
47 | |||
48 | MAX_BYTES = 10485760 | ||
49 | BACKUP_COUNT = 5 | ||
50 | FILE_FORMAT = "%(asctime)s - %(name)s - %(levelname)s - %(message)s" | ||
51 | STDOUT_FORMAT = "%(message)s" | ||
52 | |||
53 | def __init__(self): | ||
54 | self.log_level = logging.CRITICAL | ||
55 | self.directory = None | ||
56 | self._levels = {} | ||
57 | |||
58 | def set_log_level(self, level): | ||
59 | try: | ||
60 | level = self._fetch_log_level(level) | ||
61 | except InvalidLevelException: | ||
62 | pass | ||
63 | else: | ||
64 | self.log_level = level | ||
65 | |||
66 | def set_directory(self, directory): | ||
67 | if os.path.isdir(directory): | ||
68 | self.directory = directory | ||
69 | else: | ||
70 | raise NoDirectoryExistException(directory) | ||
71 | |||
72 | def get_file_message_format(self, level): | ||
73 | if not self._levels: | ||
74 | self._levels = self.LEVELS | ||
75 | level = self._fetch_log_level(level) | ||
76 | return self._levels[level][1] | ||
77 | |||
78 | def get_screen_message_format(self, level): | ||
79 | if not self._levels: | ||
80 | self._levels = self.LEVELS | ||
81 | level = self._fetch_log_level(level) | ||
82 | return self._levels[level][2] | ||
83 | |||
84 | def _fetch_log_level(self, level): | ||
85 | out = None | ||
86 | if isinstance(level, str): | ||
87 | level = level.strip().lower() | ||
88 | if level in self.LEVELS: | ||
89 | out = level | ||
90 | else: | ||
91 | for key, items in self.LEVELS.items(): | ||
92 | if level == items[0]: | ||
93 | out = key | ||
94 | if not out: | ||
95 | raise InvalidLevelException(level) | ||
96 | else: | ||
97 | return out | ||
98 | |||
99 | def _build_filepath(self, data): | ||
100 | data = os.path.normpath(data) | ||
101 | if data.startswith(os.path.sep): | ||
102 | dir = os.path.dirname(data) | ||
103 | if not os.path.isdir(dir): | ||
104 | raise NoDirectoryExistException(dir) | ||
105 | else: | ||
106 | if not self.directory: | ||
107 | raise DirectoryNotSetException() | ||
108 | else: | ||
109 | data = os.path.join(self.directory, data) | ||
110 | return data | ||
111 | |||
112 | def load(self, name): | ||
113 | log =logging.getLogger(name) | ||
114 | log.setLevel(self.log_level) | ||
115 | return log | ||
116 | |||
117 | def attach_file_handler(self, log, filename): | ||
118 | filepath = self._build_filepath(filename) | ||
119 | handler = logging.handlers.RotatingFileHandler( | ||
120 | filepath, maxBytes = self.MAX_BYTES, | ||
121 | backupCount=self.BACKUP_COUNT) | ||
122 | file_format = self.get_file_message_format(self.log_level) | ||
123 | format_obj = logging.Formatter(file_format) | ||
124 | handler.setFormatter(format_obj) | ||
125 | handler.setLevel(self.log_level) | ||
126 | log.addHandler(handler) | ||
127 | |||
128 | def attach_screen_handler(self, log, level=None): | ||
129 | if level: | ||
130 | level = self._fetch_log_level(level) | ||
131 | else: | ||
132 | level = self.log_level | ||
133 | message_format = self.get_screen_message_format(level) | ||
134 | handler = logging.StreamHandler() | ||
135 | handler.setLevel(level) | ||
136 | format_obj = logging.Formatter(message_format) | ||
137 | handler.setFormatter(format_obj) | ||
138 | log.addHandler(handler) | ||
139 | |||
140 | |||
141 | class NoDirectoryExistException(Exception): | ||
142 | pass | ||
143 | |||
144 | |||
145 | class DirectoryNotSetException(Exception): | ||
146 | pass | ||
147 | |||
148 | |||
149 | class InvalidLevelException(Exception): | ||
150 | pass | ||