1 # -----------------------------------------------------------------------
2 # Copyright (C) 2007 Georgia Public Library Service
3 # Bill Erickson <billserickson@gmail.com>
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
10 # This program 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 # -----------------------------------------------------------------------
16 import traceback, sys, os, re, threading, time
17 from osrf.const import OSRF_LOG_DEBUG, OSRF_LOG_ERR, OSRF_LOG_INFO, \
18 OSRF_LOG_INTERNAL, OSRF_LOG_TYPE_FILE, OSRF_LOG_TYPE_STDERR, \
19 OSRF_LOG_TYPE_SYSLOG, OSRF_LOG_WARN, OSRF_LOG_ACT
20 LOG_SEMAPHORE = threading.BoundedSemaphore(value=1)
23 LOG_LEVEL = OSRF_LOG_DEBUG
24 LOG_TYPE = OSRF_LOG_TYPE_STDERR
26 FRGX = re.compile('/.*/')
28 _xid = '' # the current XID
29 _xid_pfx = '' # our XID prefix
31 _xid_is_client = False # true if we are the request origin
34 def initialize(level, facility=None, logfile=None, is_client=False):
35 """Initialize the logging subsystem."""
36 global LOG_LEVEL, LOG_TYPE, LOG_FILE, _xid_is_client
38 _xid_is_client = is_client
45 sys.stderr.write("syslog not found, logging to stderr\n")
48 LOG_TYPE = OSRF_LOG_TYPE_SYSLOG
49 initialize_syslog(facility, level)
53 LOG_TYPE = OSRF_LOG_TYPE_FILE
57 global _xid, _xid_pfx, _xid_is_client, _xid_ctr
60 _xid_pfx = "%s%s" % (time.time(), os.getpid())
61 _xid = "%s%d" % (_xid_pfx, _xid_ctr)
75 # -----------------------------------------------------------------------
76 # Define wrapper functions for the log levels
77 # -----------------------------------------------------------------------
78 def log_internal(debug_str):
79 __log(OSRF_LOG_INTERNAL, debug_str)
80 def log_debug(debug_str):
81 __log(OSRF_LOG_DEBUG, debug_str)
82 def log_info(debug_str):
83 __log(OSRF_LOG_INFO, debug_str)
84 def log_warn(debug_str):
85 __log(OSRF_LOG_WARN, debug_str)
86 def log_error(debug_str):
87 __log(OSRF_LOG_ERR, debug_str)
88 def log_activity(debug_str):
89 __log(OSRF_LOG_ACT, debug_str)
91 def __log(level, msg):
92 """Builds the log message and passes the message off to the logger."""
93 global LOG_LEVEL, LOG_TYPE
98 if level == OSRF_LOG_ERR:
99 sys.stderr.write('ERR ' + msg)
102 if int(level) > int(LOG_LEVEL): return
104 # find the caller info for logging the file and line number
105 tb = traceback.extract_stack(limit=3)
109 if level == OSRF_LOG_INTERNAL:
111 if level == OSRF_LOG_INFO:
113 if level == OSRF_LOG_WARN:
115 if level == OSRF_LOG_ERR:
117 if level == OSRF_LOG_ACT:
120 filename = FRGX.sub('', tb[0])
121 msg = '[%s:%d:%s:%s:%s:%s] %s' % (lvl, os.getpid(), filename, tb[1], threading.currentThread().getName(), _xid, msg)
123 if LOG_TYPE == OSRF_LOG_TYPE_SYSLOG:
124 __log_syslog(level, msg)
126 if LOG_TYPE == OSRF_LOG_TYPE_FILE:
129 sys.stderr.write("%s\n" % msg)
131 if level == OSRF_LOG_ERR and LOG_TYPE != OSRF_LOG_TYPE_STDERR:
132 sys.stderr.write(msg + '\n')
134 def __log_syslog(level, msg):
135 ''' Logs the message to syslog '''
138 slvl = syslog.LOG_DEBUG
139 if level == OSRF_LOG_INTERNAL:
140 slvl = syslog.LOG_DEBUG
141 if level == OSRF_LOG_INFO or level == OSRF_LOG_ACT:
142 slvl = syslog.LOG_INFO
143 if level == OSRF_LOG_WARN:
144 slvl = syslog.LOG_WARNING
145 if level == OSRF_LOG_ERR:
146 slvl = syslog.LOG_ERR
148 syslog.syslog(slvl, msg)
151 ''' Logs the message to a file. '''
156 timestamp = time.strftime('%Y-%M-%d %H:%m:%S', time.localtime(epoch))
157 timestamp += '.%s' % str('%0.3f' % epoch)[-3:] # grab the millis
161 logfile = open(LOG_FILE, 'a')
163 sys.stderr.write("cannot open log file for writing: %s\n" % LOG_FILE)
164 LOG_TYPE = OSRF_LOG_TYPE_STDERR
167 LOG_SEMAPHORE.acquire()
168 logfile.write("%s %s\n" % (timestamp, msg))
170 LOG_SEMAPHORE.release()
174 def initialize_syslog(facility, level):
175 """Connect to syslog and set the logmask based on the level provided."""
180 if facility == 'local0':
181 facility = syslog.LOG_LOCAL0
182 if facility == 'local1':
183 facility = syslog.LOG_LOCAL1
184 if facility == 'local2':
185 facility = syslog.LOG_LOCAL2
186 if facility == 'local3':
187 facility = syslog.LOG_LOCAL3
188 if facility == 'local4':
189 facility = syslog.LOG_LOCAL4
190 if facility == 'local5':
191 facility = syslog.LOG_LOCAL5
192 if facility == 'local6':
193 facility = syslog.LOG_LOCAL6
194 # add other facility maps if necessary...
196 syslog.openlog(sys.argv[0], 0, facility)