cc609458cecc89c8ba4e02b404b22c1ad8978919
[pylnprof.git] / pylnprof.py
1 #!/usr/bin/python
2
3 import sys
4 import os
5 import time
6 import signal
7
8 from optparse import OptionParser
9
10 LNPROF_NS = 'sfa'
11 LNPROF_NODEID=0
12 LNPROF_ROOT='/'
13
14
15 def excepthook(t, val, tb):
16     exc_name = str(t)
17     exc_name = exc_name[18:].split("'")[0]     
18
19     count=3
20     exc=[]
21     while (count>0 and tb):
22         s = "%s:%s"%(tb.tb_frame.f_code.co_filename,tb.tb_frame.f_code.co_firstlineno)
23         s=s.replace('.','')
24         s=s.replace('/','')
25         exc.append(s)
26         tb = tb.tb_next
27         count = count - 1
28
29     inp = {'root':LNPROF_ROOT,'trace':'/'.join(exc),'exc_name':exc_name,'val':val}
30     log_path = """
31     %(root)sError/%(exc_name)s/%(trace)s/%(val)s
32     """%inp
33
34     pushlog(log_path)
35     runcron()
36
37 def handler(signum, frame):
38     if (signum==signal.SIGALRM):
39         runcron()
40
41 def runcron():
42     last_sync_file='/tmp/lnprof-sync-%s-%s'%(LNPROF_NS,LNPROF_NODEID)
43     stamp = False
44     try:
45         last_stamp = int(open(last_sync_file).read())
46         now = int(time.time())
47         if (now-last_stamp>=300):
48             commit()
49             stamp = True
50     except:
51         stamp = True
52
53     if (stamp):
54         s='%d'%int(time.time())
55         open(last_sync_file,'w').write(s)
56         signal.signal(signal.SIGALRM, handler)
57         signal.alarm(300)
58
59
60 sys.excepthook = excepthook
61
62
63 def pushlog(log_path,node_id=LNPROF_NODEID,ns=LNPROF_NS):
64     cache = open('/tmp/lnprof-%s-%s'%(ns,nodeid),'a') 
65     cache.write(log_path+'\n')
66
67 def commit(node_id=LNPROF_NODEID,ns=LNPROF_NS):
68     logpaths = {}
69     for i in range(0,1024):
70         si = '%d'%i
71         try:
72             fname = '/tmp/lnprof-%s-%d'%(ns,i)
73             logs = open(fname).readlines()
74             logs = map(lambda l:l.rstrip(),logs)
75             for l in logs:
76                 try:
77                     try:
78                         logpaths[l]['nodeset'].add(si)
79                     except KeyError:
80                         logpaths[l]={'nodeset':set([si])}
81                 except AttributeError:
82                     logpaths[l].nodeset = set([si])
83             if (not pretend):
84                 os.remove(fname)
85         except IOError:
86             pass
87     for k in logpaths.keys():
88         nodeset = list(logpaths[k]['nodeset'])
89         data = options
90         command = '/usr/bin/curl -s --cookie /tmp/fil --cookie-jar /tmp/fil -o - --data \'action=pushlog_nodes&ns=%s&nodes=%s&log_path=%s http://www.lnprof.org/command?pushlog_nodes >> /tmp/src.html'%(data.ns,','.join(nodeset),k)
91         if (pretend):
92             print command
93         else:
94             os.system(command)
95
96 def main():
97     parser = OptionParser()
98     parser.add_option("-l", "--log-path", dest="log_path",
99                   help="Log path to push", metavar="PATH")
100     parser.add_option("-n", "--nodeid",
101                   dest="nodeid", 
102                   help="Lnprof node id")
103     parser.add_option("-N", "--namespace",
104                   dest="ns", 
105                   help="Lnprof namespace")
106     parser.add_option("-k", "--api-key", dest="key",
107                   help="API key for your app", metavar="KEY", default = '')
108     parser.add_option("-p", "--pretend",
109                   dest="pretend", default=False, action="store_true",
110                   help="don't run only print")
111
112     (options, args) = parser.parse_args ()
113
114     try:
115         action = args[0]
116         if (action not in ["pushlog","commit"]):
117             raise Exception("bad action")
118     except:
119         print "Action needs to be one of pushlog and commit"
120         return
121
122     if (action=="pushlog"):
123         pushlog(options.log_path, options.node_id, options.ns)
124     elif (action=="commit"):
125         commit(options.log_path, options.node_id, options.ns) 
126
127 if __name__ == '__main__':
128     main()