-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathlogger.py
More file actions
135 lines (118 loc) · 4.5 KB
/
logger.py
File metadata and controls
135 lines (118 loc) · 4.5 KB
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
"""A very simple logger that tries to be concurrency-safe."""
import os, sys
import time
import traceback
import subprocess
import select
LOG_FILE = '/var/log/nodemanager'
LOG_SLIVERS = '/var/lib/nodemanager/getslivers.txt'
LOG_DATABASE = '/var/lib/nodemanager/database.txt'
# basically define 3 levels
LOG_NONE=0
LOG_NODE=1
LOG_VERBOSE=2
# default is to log a reasonable amount of stuff for when running on operational nodes
LOG_LEVEL=1
def set_level(level):
global LOG_LEVEL
assert level in [LOG_NONE,LOG_NODE,LOG_VERBOSE]
LOG_LEVEL=level
def verbose(msg):
log('(v) '+msg,LOG_VERBOSE)
def log(msg,level=LOG_NODE):
"""Write <msg> to the log file if level >= current log level (default LOG_NODE)."""
if (level > LOG_LEVEL):
return
try:
fd = os.open(LOG_FILE, os.O_WRONLY | os.O_CREAT | os.O_APPEND, 0600)
if not msg.endswith('\n'): msg += '\n'
os.write(fd, '%s: %s' % (time.asctime(time.gmtime()), msg))
os.close(fd)
except OSError:
sys.stderr.write(msg)
sys.stderr.flush()
def log_exc(msg="",name=None):
"""Log the traceback resulting from an exception."""
if name:
log("%s: EXCEPTION caught <%s> \n %s" %(name, msg, traceback.format_exc()))
else:
log("EXCEPTION caught <%s> \n %s" %(msg, traceback.format_exc()))
########## snapshot data to a file
# for some reason the various modules are still triggered even when the
# data from PLC cannot be reached
# we show this message instead of the exception stack instead in this case
def log_missing_data (msg,key):
log("%s: could not find the %s key in data (PLC connection down?) - IGNORED"%(msg,key))
def log_data_in_file (data, file, message="",level=LOG_NODE):
if (level > LOG_LEVEL):
return
import pprint, time
try:
f=open(file,'w')
now=time.strftime("Last update: %Y.%m.%d at %H:%M:%S %Z", time.localtime())
f.write(now+'\n')
if message: f.write('Message:'+message+'\n')
pp=pprint.PrettyPrinter(stream=f,indent=2)
pp.pprint(data)
f.close()
verbose("logger:.log_data_in_file Owerwrote %s"%file)
except:
log_exc('logger.log_data_in_file failed - file=%s - message=%r'%(file,message))
def log_slivers (data):
log_data_in_file (data, LOG_SLIVERS, "raw GetSlivers")
def log_database (db):
log_data_in_file (db, LOG_DATABASE, "raw database")
#################### child processes
# avoid waiting until the process returns;
# that makes debugging of hanging children hard
class Buffer:
def __init__ (self,message='log_call: '):
self.buffer=''
self.message=message
def add (self,c):
self.buffer += c
if c=='\n': self.flush()
def flush (self):
if self.buffer:
log (self.message + self.buffer)
self.buffer=''
# time out in seconds - avoid hanging subprocesses - default is 5 minutes
default_timeout_minutes=5
# returns a bool that is True when everything goes fine and the retcod is 0
def log_call(command,timeout=default_timeout_minutes*60,poll=1):
message=" ".join(command)
log("log_call: running command %s" % message)
verbose("log_call: timeout=%r s" % timeout)
verbose("log_call: poll=%r s" % poll)
trigger=time.time()+timeout
result = False
try:
child = subprocess.Popen(command, bufsize=1,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True)
buffer = Buffer()
while True:
# see if anything can be read within the poll interval
(r,w,x)=select.select([child.stdout],[],[],poll)
if r: buffer.add(child.stdout.read(1))
# is process over ?
returncode=child.poll()
# yes
if returncode != None:
buffer.flush()
# child is done and return 0
if returncode == 0:
log("log_call:end command (%s) completed" % message)
result=True
break
# child has failed
else:
log("log_call:end command (%s) returned with code %d" %(message,returncode))
break
# no : still within timeout ?
if time.time() >= trigger:
buffer.flush()
child.terminate()
log("log_call:end terminating command (%s) - exceeded timeout %d s"%(message,timeout))
break
except: log_exc("failed to run command %s" % message)
return result