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
|
# -*- encoding: utf-8 -*-
'''
log.py
------
Logging for leap_mx.
@authors: Isis Agora Lovecruft, <isis@leap.se> 0x2cdb8b35
@licence: see included LICENSE file
@copyright: 2013 Isis Agora Lovecruft
'''
from __future__ import print_function
from datetime import datetime
from functools import wraps
import logging
import os
import sys
import time
import traceback
from twisted.python import log as txlog
from twisted.python import util as txutil
from twisted.python import logfile as txlogfile
from twisted.python.failure import Failure
from leap.mx.util import version, config
class InvalidTimestampFormat(Exception):
pass
class UnprefixedLogfile(txlog.FileLogObserver):
"""Logfile with plain messages, without timestamp prefixes."""
def emit(self, eventDict):
text = txlog.textFromEventDict(eventDict)
if text is None:
return
txutil.untilConcludes(self.write, "%s\n" % text)
txutil.untilConcludes(self.flush)
def utcDateNow():
"""The current date for UTC time."""
return datetime.utcnow()
def utcTimeNow():
"""Seconds since epoch in UTC time, as type float."""
return time.mktime(time.gmtime())
def dateToTime(date):
"""Convert datetime to seconds since epoch."""
return time.mktime(date.timetuple())
def prettyDateNow():
"""Pretty string for the local time."""
return datetime.now().ctime()
def utcPrettyDateNow():
"""Pretty string for UTC."""
return datetime.utcnow().ctime()
def timeToPrettyDate(time_val):
"""Convert seconds since epoch to date."""
return time.ctime(time_val)
def start(logfilename=None, logfiledir=None):
"""
Start logging to stdout, and optionally to a logfile as well.
@param logfile: The full path of the filename to store logs in.
"""
txlog.startLoggingWithObserver(UnprefixedLogfile(sys.stdout).emit)
if logfilename and logfiledir:
if not os.path.isdir(logfiledir):
os.makedirs(logfiledir)
daily_logfile = txlogfile.DailyLogFile(logfilename, logfiledir)
txlog.addObserver(txlog.FileLogObserver(daily_logfile).emit)
txlog.msg("Starting %s, version %s, on %s UTC" % (version.getPackageName(),
version.getVersion(),
utcPrettyDateNow()))
txlog.msg("Authors: %s" % version.getAuthors())
def msg(msg, *arg, **kwarg):
"""Log a message at the INFO level."""
print("[*] %s" % msg)
def debug(msg, *arg, **kwarg):
"""Log a message at the DEBUG level."""
if config.advanced.debug:
print("[d] %s" % msg)
def warn(msg, *arg, **kwarg):
"""Log a message at the WARN level."""
if config.basic.show_warnings:
txlog.logging.captureWarnings('true')
print("[#] %s" % msg)
def err(msg, *arg, **kwarg):
"""Log a message at the ERROR level."""
print("[!] %s" % msg)
def fail(*failure):
"""Log a message at the CRITICAL level."""
logging.critical(failure)
## xxx should we take steps to exit here?
def exception(error):
"""
Catch an exception and print only the error message, then continue normal
program execution.
@param error: Can be error messages printed to stdout and to the
logfile, or can be a twisted.python.failure.Failure instance.
"""
if isinstance(error, Failure):
error.printTraceback()
else:
exc_type, exc_value, exc_traceback = sys.exc_info()
traceback.print_exception(exc_type, exc_value, exc_traceback)
def catch(func):
"""
Quick wrapper to add around test methods for debugging purposes,
catches the given Exception. Use like so:
>>> @log.catch
def foo(bar):
if bar == 'baz':
raise Exception("catch me no matter what I am")
>>> foo("baz")
[!] catch me no matter what I am
"""
@wraps(func)
def _catch(*args, **kwargs):
try:
func(*args, **kwargs)
except Exception, exc:
exception(exc)
return _catch
|