OLD | NEW |
(Empty) | |
| 1 #!/usr/bin/env python |
| 2 |
| 3 """This script runs 1 minute worth of load tests. |
| 4 |
| 5 It is meant to be run from a cron job every minute. |
| 6 """ |
| 7 |
| 8 import json |
| 9 import httplib2 |
| 10 import logging |
| 11 import multiprocessing |
| 12 import os |
| 13 import random |
| 14 import sys |
| 15 import urllib2 |
| 16 import threading |
| 17 import time |
| 18 |
| 19 import googleapiclient.http |
| 20 from oauth2client.client import GoogleCredentials |
| 21 |
| 22 ENDPOINT_TO_TEST = 'https://chrome-infra-mon-proxy.appspot.com/monacq' |
| 23 AUTHORIZE = True |
| 24 METHOD = 'POST' |
| 25 CREDENTIALS = '.loadtest_credentials.json' |
| 26 SCOPES = 'https://www.googleapis.com/auth/userinfo.email' |
| 27 QPS_URL = 'https://test-dot-chrome-infra-mon-proxy.appspot.com/loadtest/' |
| 28 PAYLOAD_SIZE = 6000 # In bytes. |
| 29 PAYLOAD_TIMEOUT = 10 # In seconds. |
| 30 |
| 31 |
| 32 class LoadTest(object): |
| 33 def __init__(self): |
| 34 self.qps = 0 |
| 35 self.payload = '' |
| 36 self.credentials = GoogleCredentials.from_stream(CREDENTIALS) |
| 37 self.credentials = self.credentials.create_scoped(SCOPES) |
| 38 self.http = httplib2.Http() |
| 39 self.authorize() |
| 40 |
| 41 def authorize(self): |
| 42 if AUTHORIZE: |
| 43 self.http = self.credentials.authorize(self.http) |
| 44 |
| 45 def refresh_token(self): |
| 46 if AUTHORIZE and self.credentials.access_token_expired: |
| 47 print 'Refreshing oauth2 token' |
| 48 self.authorize() |
| 49 |
| 50 def update_qps(self): |
| 51 response = urllib2.urlopen(QPS_URL, timeout=15) |
| 52 data = json.loads(response.read()) |
| 53 self.qps = data.get('qps', 0) |
| 54 payload_size = data.get('payload_size', PAYLOAD_SIZE) |
| 55 self.payload = ''.join( |
| 56 chr(random.randint(0, 255)) for i in xrange(payload_size)) |
| 57 self.refresh_token() |
| 58 |
| 59 def send_one_request(self): |
| 60 url = ENDPOINT_TO_TEST |
| 61 headers = { |
| 62 'content-length': str(len(self.payload)), |
| 63 'content-type': 'application/x-protobuf', |
| 64 } |
| 65 def callback(_response, _content): |
| 66 pass |
| 67 if METHOD == 'POST': |
| 68 request = googleapiclient.http.HttpRequest( |
| 69 self.http, callback, url, method=METHOD, |
| 70 body=self.payload, |
| 71 headers=headers) |
| 72 else: |
| 73 request = googleapiclient.http.HttpRequest( |
| 74 self.http, callback, url, method=METHOD, headers={}) |
| 75 request.execute() |
| 76 |
| 77 def send_n_requests(self, n): |
| 78 """Spawn ``n`` parallel processes each sending a single request.""" |
| 79 procs = [ |
| 80 multiprocessing.Process( |
| 81 # pylint: disable=unnecessary-lambda |
| 82 target=lambda: self.send_one_request(), |
| 83 args=[], |
| 84 name='run %d' % n, |
| 85 ) for n in xrange(n)] |
| 86 for p in procs: |
| 87 p.daemon = True |
| 88 p.start() |
| 89 for p in procs: |
| 90 p.join(timeout=PAYLOAD_TIMEOUT) |
| 91 # Clear runaway processes. |
| 92 for p in procs: |
| 93 if p.is_alive(): |
| 94 p.terminate() |
| 95 |
| 96 |
| 97 def main(): |
| 98 # Run 1 minute worth of load test. |
| 99 lt = LoadTest() |
| 100 lt.update_qps() |
| 101 if not lt.qps: |
| 102 return 0 |
| 103 for _ in xrange(60): |
| 104 time_start = time.time() |
| 105 # Send lt.qps number of requests every second, asynchronously. |
| 106 proc = threading.Thread( |
| 107 target=lambda: lt.send_n_requests(lt.qps), |
| 108 args=[], |
| 109 name='queue %d' % time_start) |
| 110 proc.start() |
| 111 time.sleep(1.0) |
| 112 |
| 113 |
| 114 if __name__ == '__main__': |
| 115 sys.exit(main()) |
OLD | NEW |