1 # Copyright (c) 2015 The Chromium Authors. All rights reserved. 2 # Use of this source code is governed by a BSD-style license that can be 3 # found in the LICENSE file. 4 5 import json 6 import logging 7 import os 8 import re 9 import webapp2 10 import uuid 11 12 from . import trace_info 13 from . import cloud_config 14 15 import cloudstorage as gcs 16 17 from google.appengine.api import datastore_errors 18 19 default_retry_params = gcs.RetryParams(initial_delay=0.2, 20 max_delay=5.0, 21 backoff_factor=2, 22 max_retry_period=15) 23 gcs.set_default_retry_params(default_retry_params) 24 25 26 class UploadPage(webapp2.RequestHandler): 27 28 def get(self): 29 self.response.out.write(""" 30 <html><body> 31 <head><title>Performance Insights - Trace Uploader</title></head> 32 <form action="/upload" enctype="multipart/form-data" method="post"> 33 <div><input type="file" name="trace"/></div> 34 <div><input type="submit" value="Upload"></div> 35 </form><hr> 36 </body></html>""") 37 38 def post(self): 39 trace_uuid = str(uuid.uuid4()) 40 41 gcs_path = '/%s/%s.gz' % ( 42 cloud_config.Get().trace_upload_bucket, trace_uuid) 43 gcs_file = gcs.open(gcs_path, 44 'w', 45 content_type='application/octet-stream', 46 options={}, 47 retry_params=default_retry_params) 48 gcs_file.write(self.request.get('trace')) 49 gcs_file.close() 50 51 trace_object = trace_info.TraceInfo(id=trace_uuid) 52 trace_object.remote_addr = os.environ["REMOTE_ADDR"] 53 54 for arg in self.request.arguments(): 55 arg_key = arg.replace('-', '_').lower() 56 if arg_key in trace_object._properties: 57 try: 58 setattr(trace_object, arg_key, self.request.get(arg)) 59 except datastore_errors.BadValueError: 60 pass 61 62 scenario_config = self.request.get('config') 63 if scenario_config: 64 config_json = json.loads(scenario_config) 65 if 'scenario_name' in config_json: 66 trace_object.scenario_name = config_json['scenario_name'] 67 68 tags_string = self.request.get('tags') 69 if tags_string: 70 # Tags are comma separated and should only include alphanumeric + '-'. 71 if re.match('^[a-zA-Z0-9-,]+$', tags_string): 72 trace_object.tags = tags_string.split(',') 73 else: 74 logging.warning('The provided tags string includes one or more invalid' 75 ' characters and will be ignored') 76 77 trace_object.ver = self.request.get('product-version') 78 trace_object.put() 79 80 self.response.write(trace_uuid) 81 82 app = webapp2.WSGIApplication([('/upload', UploadPage)]) 83