|
|
@@ -69,6 +69,122 @@ class BasicLogger(ILogger): |
|
|
|
|
|
|
|
_LoggerClass = BasicLogger |
|
|
|
|
|
|
|
|
|
|
|
class GLRecord(dict): |
|
|
|
"""Grid Logging Best Practices Record, Distributed Logging Utilities |
|
|
|
|
|
|
|
The following names are reserved: |
|
|
|
|
|
|
|
event -- log event name |
|
|
|
Below is EBNF for the event name part of a log message. |
|
|
|
name = <nodot> ( "." <name> )? |
|
|
|
nodot = {RFC3896-chars except "."} |
|
|
|
|
|
|
|
Suffixes: |
|
|
|
start: Immediately before the first action in a task. |
|
|
|
end: Immediately after the last action in a task (that succeeded). |
|
|
|
error: an error condition that does not correspond to an end event. |
|
|
|
|
|
|
|
date -- timestamp |
|
|
|
level -- logging level (see levels below) |
|
|
|
status -- integer status code |
|
|
|
gid -- global grid identifier |
|
|
|
gid, cgid -- parent/child identifiers |
|
|
|
prog -- program name |
|
|
|
|
|
|
|
|
|
|
|
More info: http://www.cedps.net/wiki/index.php/LoggingBestPractices#Python |
|
|
|
|
|
|
|
reserved -- list of reserved names, |
|
|
|
omitname -- list of reserved names, output only values |
|
|
|
levels -- dict of levels and description |
|
|
|
""" |
|
|
|
reserved = ('date', 'event', 'level', 'status', 'gid', 'prog') |
|
|
|
omitname = ('date', 'event',) |
|
|
|
levels = dict(FATAL='Component cannot continue, or system is unusable.', |
|
|
|
ALERT='Action must be taken immediately.', |
|
|
|
CRITICAL='Critical conditions (on the system).', |
|
|
|
ERROR='Errors in the component; not errors from elsewhere.', |
|
|
|
WARNING='Problems that are recovered from, usually.', |
|
|
|
NOTICE='Normal but significant condition.', |
|
|
|
INFO='Informational messages that would be useful to a deployer or administrator.', |
|
|
|
DEBUG='Lower level information concerning program logic decisions, internal state, etc.', |
|
|
|
TRACE='Finest granularity, similar to "stepping through" the component or system.', |
|
|
|
) |
|
|
|
|
|
|
|
def __init__(self, date=None, **kw): |
|
|
|
kw['date'] = date or self.GLDate() |
|
|
|
dict.__init__(self, kw) |
|
|
|
|
|
|
|
def __str__(self): |
|
|
|
""" |
|
|
|
""" |
|
|
|
from cStringIO import StringIO |
|
|
|
s = StringIO(); n = " " |
|
|
|
reserved = self.reserved; omitname = self.omitname; levels = self.levels |
|
|
|
|
|
|
|
for k in ( list(filter(lambda i: self.has_key(i), reserved)) + |
|
|
|
list(filter(lambda i: i not in reserved, self.keys())) |
|
|
|
): |
|
|
|
v = self[k] |
|
|
|
if k in omitname: |
|
|
|
s.write( "%s " %self.format[type(v)](v) ) |
|
|
|
continue |
|
|
|
|
|
|
|
if k == reserved[2] and v not in levels: |
|
|
|
pass |
|
|
|
|
|
|
|
s.write( "%s=%s " %(k, self.format[type(v)](v) ) ) |
|
|
|
|
|
|
|
s.write("\n") |
|
|
|
return s.getvalue() |
|
|
|
|
|
|
|
class GLDate(str): |
|
|
|
"""Grid logging Date Format |
|
|
|
all timestamps should all be in the same time zone (UTC). |
|
|
|
Grid timestamp value format that is a highly readable variant of the ISO8601 time standard [1]: |
|
|
|
|
|
|
|
YYYY-MM-DDTHH:MM:SS.SSSSSSZ |
|
|
|
|
|
|
|
""" |
|
|
|
def __new__(self, args=None): |
|
|
|
"""args -- datetime (year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]]) |
|
|
|
""" |
|
|
|
import datetime |
|
|
|
args = args or datetime.datetime.utcnow() |
|
|
|
l = (args.year, args.month, args.day, args.hour, args.minute, args.second, |
|
|
|
args.microsecond, args.tzinfo or 'Z') |
|
|
|
|
|
|
|
return str.__new__(self, "%04d-%02d-%02dT%02d:%02d:%02d.%06d%s" %l) |
|
|
|
|
|
|
|
format = { int:str, float:lambda x: "%lf" % x, long:str, str:lambda x:x, |
|
|
|
unicode:str, GLDate:str, } |
|
|
|
|
|
|
|
|
|
|
|
def sendGridLog(**kw): |
|
|
|
"""Send GLRecord, Distributed Logging Utilities |
|
|
|
""" |
|
|
|
import os |
|
|
|
from socket import socket, AF_INET, SOCK_DGRAM |
|
|
|
if not bool(os.environ.get('GRIDLOG_ON', False)): |
|
|
|
return |
|
|
|
|
|
|
|
url = os.environ.get('GRIDLOG_DEST') |
|
|
|
if url is None: |
|
|
|
return |
|
|
|
|
|
|
|
try: |
|
|
|
idx1 = url.find('://') + 3 |
|
|
|
idx2 = url.find('/', idx1) |
|
|
|
if idx2 < idx1: idx2 = len(url) |
|
|
|
netloc = url[idx1:idx2] |
|
|
|
host,port = (netloc.split(':')+[80])[0:2] |
|
|
|
socket(AF_INET, SOCK_DGRAM).sendto( str(GLRecord(**kw)), |
|
|
|
(host,int(port)),) |
|
|
|
except Exception, ex: |
|
|
|
print >>sys.stderr, "*** gridlog failed -- %s" %(str(kw)) |
|
|
|
|
|
|
|
|
|
|
|
def setBasicLogger(): |
|
|
|
'''Use Basic Logger. |
|
|
|
''' |
|
|
|