python3: Use higher-resolution CPU timer.
[ashd.git] / python3 / ashd / perf.py
1 import collections
2 try:
3     import pdm.perf
4 except:
5     pdm = None
6 try:
7     import time
8     clock_thread = time.CLOCK_THREAD_CPUTIME_ID
9 except:
10     clock_thread = None
11
12 reqstat = {}
13
14 if pdm:
15     statistics = pdm.perf.staticdir()
16     statistics["req"] = pdm.perf.valueattr(reqstat)
17     requests = pdm.perf.eventobj()
18
19     class reqstart(pdm.perf.startevent):
20         def __init__(self, env):
21             super().__init__()
22             self.method = env.get("REQUEST_METHOD")
23             self.uri = env.get("REQUEST_URI")
24             self.host = env.get("HTTP_HOST")
25             self.script_uri = env.get("SCRIPT_NAME")
26             self.script_path = env.get("SCRIPT_FILENAME")
27             self.pathinfo = env.get("PATH_INFO")
28             self.querystring = env.get("QUERY_STRING")
29             self.remoteaddr = env.get("REMOTE_ADDR")
30             self.remoteport = env.get("REMOTE_PORT")
31             self.scheme = env.get("wsgi.url_scheme")
32             if clock_thread is not None:
33                 self.icpu = time.clock_gettime(clock_thread)
34
35     class reqfinish(pdm.perf.finishevent):
36         def __init__(self, start, aborted, status):
37             super().__init__(start, aborted)
38             self.status = status
39             self.cputime = 0
40             if clock_thread is not None:
41                 self.cputime = time.clock_gettime(clock_thread) - start.icpu
42
43 class request(object):
44     def __init__(self, env):
45         self.resp = None
46         if pdm:
47             self.startev = reqstart(env)
48             requests.notify(self.startev)
49
50     def response(self, resp):
51         self.resp = resp
52
53     def finish(self, aborted):
54         key = None
55         status = None
56         try:
57             if len(self.resp) > 0:
58                 status = self.resp[0]
59                 if isinstance(status, collections.ByteString):
60                     status = status.decode("latin-1")
61                 else:
62                     status = str(status)
63                 p = status.find(" ")
64                 if p < 0:
65                     key = status
66                 else:
67                     key = status[:p]
68         except:
69             pass
70         reqstat[key] = reqstat.setdefault(key, 0) + 1
71         if pdm:
72             requests.notify(reqfinish(self.startev, aborted, status))
73
74     def __enter__(self):
75         return self
76     
77     def __exit__(self, *excinfo):
78         self.finish(bool(excinfo[0]))
79         return False