forked from heldersepu/GMapCatcher
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmapLogging.py
181 lines (145 loc) · 6.01 KB
/
mapLogging.py
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
178
179
180
181
## @package gmapcatcher.mapLogging
# Logging for gmapcatcher
"""
Logging for GMapCatcher
Purpose - primary for developers to manage debug messages. Secondary - users after setting
'--logging-path=/tmp/maps.log' will catch all messages in file and can send them for checking
what went wrong in error reporting.
Usage:
- don't use print / print_exc etc commands for output debug/info/error messages
- in module import logging 'import logging'
- get logger 'log = logging.getLogger()'
That's 2 lines at the top of the module.
In source code use:
log.debug(msg)
log.info(msg)
log.warning(msg)
log.error(msg)
log.exception(exception)
log.critical(msg)
Now use log.<method> to print debug/info/error messages anywhere in the code.
For users:
==========
Production setup is:
- output to stdout: info, warning
- output to stderr: error, critical
- output to file: default None. If set on command line '--logging-path=/tmp/map.log'
All messages from debug are logged in file.
For developers:
===============
- it is possible/welcom/convenient to put many debug outputs in the source code. While debugging it's good to
have this helper output. After things are OK, just set log level to production setting and messages
woun't be displayed.
If there is a need to see debug messages again just set logging level to debug.
There will be plenty of debug messages printed on the screen/file. It's simple to use 'grep' for
selecting what messages shold be listed.
cat maps.log | grep "only_my_module"
cat maps.log | grep -v "not_this_module" | grep -v "not_that_module"
after setting DEBUG for stdout: maps.py | grep -v "not_this_module" | grep -v "not_that_module"
Use grep from gnuwin32 for windows (http://gnuwin32.sourceforge.net/packages/grep.htm).
"""
import sys
import os
import logging
from traceback import print_exc
from mapConst import DEFAULT_PATH
log = logging.getLogger()
import fileUtils
LOGGING_STDOUT = True
LOGGING_STDOUT_LEVEL_ABOVE_OR_EQUAL = logging.INFO
LOGGING_STDOUT_LEVEL_BELOW = logging.ERROR
LOGGING_STDOUT_FORMAT = "%(message)s"
LOGGING_STDERR = True
LOGGING_STDERR_LEVEL_ABOVE_OR_EQUAL = logging.ERROR
LOGGING_STDERR_FORMAT = "%(message)s"
LOGGING_FILE = True
LOGGING_FILE_LEVEL_ABOVE_OR_EQUAL = logging.DEBUG
LOGGING_FILE_FORMAT = "%(asctime)s - %(levelname)s - %(thread)d - %(module)s:%(lineno)d - %(message)s"
#LOGGING_FILE_NAME = "maps.log"
# if set to none, it's possible to override using command line parameter '--logging-path'
LOGGING_FILE_NAME = None
LOGGING_FILE_MODE = "w"
class FilterSevereOut(logging.Filter):
def __init__(self, name=None, severity=logging.NOTSET):
self.severeout = severity
if name is not None:
logging.Filter.__init__(self, name)
else:
logging.Filter.__init__(self)
def filter(self, record):
if record.levelno < self.severeout:
# we allow everything below severity self.severeout
return 1
else:
return 0
## Returns the Path to the logging file
def get_loggingpath(loggingpath=None):
if loggingpath is None:
if LOGGING_FILE_NAME is not None:
# the config file must be found at DEFAULT_PATH
loggingpath = os.path.expanduser(DEFAULT_PATH)
fileUtils.check_dir(loggingpath)
loggingpath = os.path.join(loggingpath, LOGGING_FILE_NAME)
return loggingpath
else:
return loggingpath
def init_logging(loggingpath=None):
"""initialization of logging
LOGGING_STDOUT / LOGGING_STDERR / LOGGING_FILE - True/False - allow/deny strem
only STDOUT has 'LOGGING_STDOUT_LEVEL_BELOW'
LOGGING_FILE_NAME is None or just a filename. If it's None it means only option how to set up
logging is using command line. If LOGGING_FILE_NAME is used, optional commandline parameter
overrides LOGGING_FILE_NAME.
"""
log.cur_level = logging.ERROR
log.setLevel(log.cur_level)
if LOGGING_STDOUT:
hsout = None
try:
hsout = logging.StreamHandler(sys.stdout)
hsout.setFormatter(logging.Formatter(LOGGING_STDOUT_FORMAT))
hsout.setLevel(LOGGING_STDOUT_LEVEL_ABOVE_OR_EQUAL)
hsout.addFilter(FilterSevereOut(name=None, severity=LOGGING_STDOUT_LEVEL_BELOW))
log.addHandler(hsout)
if(LOGGING_STDOUT_LEVEL_ABOVE_OR_EQUAL < log.cur_level):
log.cur_level = LOGGING_STDOUT_LEVEL_ABOVE_OR_EQUAL
log.setLevel(log.cur_level)
log.info("Logging to stdout is set.")
except Exception, ex:
if hsout is not None:
log.removeHandler(hsout)
print_exc()
if LOGGING_STDERR:
hserr = None
try:
hserr = logging.StreamHandler(sys.stderr)
hserr.setFormatter(logging.Formatter(LOGGING_STDERR_FORMAT))
hserr.setLevel(LOGGING_STDERR_LEVEL_ABOVE_OR_EQUAL)
log.addHandler(hserr)
if(LOGGING_STDERR_LEVEL_ABOVE_OR_EQUAL < log.cur_level):
log.cur_level = LOGGING_STDERR_LEVEL_ABOVE_OR_EQUAL
log.setLevel(log.cur_level)
log.info("Logging to stderror is set.")
except Exception, ex:
if hserr is not None:
log.removeHandler(hserr)
log.exception(ex)
if LOGGING_FILE:
filename = get_loggingpath(loggingpath)
if filename is None:
return
hf = None
try:
hf = logging.FileHandler(filename, LOGGING_FILE_MODE)
hf.setFormatter(logging.Formatter(LOGGING_FILE_FORMAT))
hf.setLevel(LOGGING_FILE_LEVEL_ABOVE_OR_EQUAL)
log.addHandler(hf)
if(LOGGING_FILE_LEVEL_ABOVE_OR_EQUAL < log.cur_level):
log.cur_level = LOGGING_FILE_LEVEL_ABOVE_OR_EQUAL
log.setLevel(log.cur_level)
log.info("Logging to file is set to " + str(filename) + ".")
except Exception, ex:
# we have error while logging to file, remove handler and continue
if hf is not None:
log.removeHandler(hf)
log.exception(ex)