comparison mercurial/keepalive.py @ 40032:dc82ad1b7f77

keepalive: track request count and bytes sent I want wire protocol interactions to report the number of requests made and bytes transferred. This commit teaches the very low-level custom HTTPConnection class to track the number of bytes sent to the socket. This may vary from the number of bytes that go on the wire due to e.g. TLS. That's OK. KeepAliveHandler is taught to track the total number of requests and total number of bytes sent across all requests. Differential Revision: https://phab.mercurial-scm.org/D4856
author Gregory Szorc <gregory.szorc@gmail.com>
date Mon, 01 Oct 2018 12:02:54 -0700
parents f2dffa1359c6
children 5e5b06087ec5
comparison
equal deleted inserted replaced
40031:f2dffa1359c6 40032:dc82ad1b7f77
172 return dict(self._hostmap) 172 return dict(self._hostmap)
173 173
174 class KeepAliveHandler(object): 174 class KeepAliveHandler(object):
175 def __init__(self): 175 def __init__(self):
176 self._cm = ConnectionManager() 176 self._cm = ConnectionManager()
177 self.requestscount = 0
178 self.sentbytescount = 0
177 179
178 #### Connection Management 180 #### Connection Management
179 def open_connections(self): 181 def open_connections(self):
180 """return a list of connected hosts and the number of connections 182 """return a list of connected hosts and the number of connections
181 to each. [('foo.com:80', 2), ('bar.org', 1)]""" 183 to each. [('foo.com:80', 2), ('bar.org', 1)]"""
310 DEBUG.info("re-using connection to %s (%d)", host, id(h)) 312 DEBUG.info("re-using connection to %s (%d)", host, id(h))
311 313
312 return r 314 return r
313 315
314 def _start_transaction(self, h, req): 316 def _start_transaction(self, h, req):
317 oldbytescount = h.sentbytescount
318
315 # What follows mostly reimplements HTTPConnection.request() 319 # What follows mostly reimplements HTTPConnection.request()
316 # except it adds self.parent.addheaders in the mix and sends headers 320 # except it adds self.parent.addheaders in the mix and sends headers
317 # in a deterministic order (to make testing easier). 321 # in a deterministic order (to make testing easier).
318 headers = util.sortdict(self.parent.addheaders) 322 headers = util.sortdict(self.parent.addheaders)
319 headers.update(sorted(req.headers.items())) 323 headers.update(sorted(req.headers.items()))
344 h.putheader(k, v) 348 h.putheader(k, v)
345 h.endheaders() 349 h.endheaders()
346 if urllibcompat.hasdata(req): 350 if urllibcompat.hasdata(req):
347 h.send(data) 351 h.send(data)
348 352
353 # This will fail to record events in case of I/O failure. That's OK.
354 self.requestscount += 1
355 self.sentbytescount += h.sentbytescount - oldbytescount
356
357 try:
358 self.parent.requestscount += 1
359 self.parent.sentbytescount += h.sentbytescount - oldbytescount
360 except AttributeError:
361 pass
362
349 class HTTPHandler(KeepAliveHandler, urlreq.httphandler): 363 class HTTPHandler(KeepAliveHandler, urlreq.httphandler):
350 pass 364 pass
351 365
352 class HTTPResponse(httplib.HTTPResponse): 366 class HTTPResponse(httplib.HTTPResponse):
353 # we need to subclass HTTPResponse in order to 367 # we need to subclass HTTPResponse in order to
583 if self.debuglevel > 0: 597 if self.debuglevel > 0:
584 print("sending a read()able") 598 print("sending a read()able")
585 data = read(blocksize) 599 data = read(blocksize)
586 while data: 600 while data:
587 self.sock.sendall(data) 601 self.sock.sendall(data)
602 self.sentbytescount += len(data)
588 data = read(blocksize) 603 data = read(blocksize)
589 else: 604 else:
590 self.sock.sendall(str) 605 self.sock.sendall(str)
606 self.sentbytescount += len(str)
591 except socket.error as v: 607 except socket.error as v:
592 reraise = True 608 reraise = True
593 if v[0] == errno.EPIPE: # Broken pipe 609 if v[0] == errno.EPIPE: # Broken pipe
594 if self._HTTPConnection__state == httplib._CS_REQ_SENT: 610 if self._HTTPConnection__state == httplib._CS_REQ_SENT:
595 self._broken_pipe_resp = None 611 self._broken_pipe_resp = None
622 # use the modified response class 638 # use the modified response class
623 response_class = HTTPResponse 639 response_class = HTTPResponse
624 send = safesend 640 send = safesend
625 getresponse = wrapgetresponse(httplib.HTTPConnection) 641 getresponse = wrapgetresponse(httplib.HTTPConnection)
626 642
643 def __init__(self, *args, **kwargs):
644 httplib.HTTPConnection.__init__(self, *args, **kwargs)
645 self.sentbytescount = 0
627 646
628 ######################################################################### 647 #########################################################################
629 ##### TEST FUNCTIONS 648 ##### TEST FUNCTIONS
630 ######################################################################### 649 #########################################################################
631 650