| OLD | NEW |
| 1 # Copyright (c) 2016 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2016 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """Represents the trace of a page load.""" | 5 """Represents the trace of a page load.""" |
| 6 | 6 |
| 7 import datetime | 7 import datetime |
| 8 try: | 8 try: |
| 9 import ujson as json | 9 import ujson as json |
| 10 except ImportError: | 10 except ImportError: |
| 11 import json | 11 import json |
| 12 import time | 12 import time |
| 13 | 13 |
| 14 import devtools_monitor | 14 import devtools_monitor |
| 15 import page_track | 15 import page_track |
| 16 import request_track | 16 import request_track |
| 17 import tracing | 17 import tracing_track |
| 18 | 18 |
| 19 | 19 |
| 20 class LoadingTrace(object): | 20 class LoadingTrace(object): |
| 21 """Represents the trace of a page load.""" | 21 """Represents the trace of a page load.""" |
| 22 _URL_KEY = 'url' | 22 _URL_KEY = 'url' |
| 23 _METADATA_KEY = 'metadata' | 23 _METADATA_KEY = 'metadata' |
| 24 _PAGE_KEY = 'page_track' | 24 _PAGE_KEY = 'page_track' |
| 25 _REQUEST_KEY = 'request_track' | 25 _REQUEST_KEY = 'request_track' |
| 26 _TRACING_KEY = 'tracing_track' | 26 _TRACING_KEY = 'tracing_track' |
| 27 | 27 |
| 28 def __init__(self, url, metadata, page, request, tracing_track): | 28 def __init__(self, url, metadata, page, request, track): |
| 29 """Initializes a loading trace instance. | 29 """Initializes a loading trace instance. |
| 30 | 30 |
| 31 Args: | 31 Args: |
| 32 url: (str) URL that has been loaded | 32 url: (str) URL that has been loaded |
| 33 metadata: (dict) Metadata associated with the load. | 33 metadata: (dict) Metadata associated with the load. |
| 34 page: (PageTrack) instance of PageTrack. | 34 page: (PageTrack) instance of PageTrack. |
| 35 request: (RequestTrack) instance of RequestTrack. | 35 request: (RequestTrack) instance of RequestTrack. |
| 36 tracing_track: (TracingTrack) instance of TracingTrack. | 36 track: (TracingTrack) instance of TracingTrack. |
| 37 """ | 37 """ |
| 38 self.url = url | 38 self.url = url |
| 39 self.metadata = metadata | 39 self.metadata = metadata |
| 40 self.page_track = page | 40 self.page_track = page |
| 41 self.request_track = request | 41 self.request_track = request |
| 42 self._tracing_track = tracing_track | 42 self._tracing_track = track |
| 43 self._tracing_json_str = None | 43 self._tracing_json_str = None |
| 44 | 44 |
| 45 def ToJsonDict(self): | 45 def ToJsonDict(self): |
| 46 """Returns a dictionary representing this instance.""" | 46 """Returns a dictionary representing this instance.""" |
| 47 result = {self._URL_KEY: self.url, self._METADATA_KEY: self.metadata, | 47 result = {self._URL_KEY: self.url, self._METADATA_KEY: self.metadata, |
| 48 self._PAGE_KEY: self.page_track.ToJsonDict(), | 48 self._PAGE_KEY: self.page_track.ToJsonDict(), |
| 49 self._REQUEST_KEY: self.request_track.ToJsonDict(), | 49 self._REQUEST_KEY: self.request_track.ToJsonDict(), |
| 50 self._TRACING_KEY: (self.tracing_track.ToJsonDict() | 50 self._TRACING_KEY: (self.tracing_track.ToJsonDict() |
| 51 if self.tracing_track else None)} | 51 if self.tracing_track else None)} |
| 52 return result | 52 return result |
| 53 | 53 |
| 54 def ToJsonFile(self, json_path): | 54 def ToJsonFile(self, json_path): |
| 55 """Save a json file representing this instance.""" | 55 """Save a json file representing this instance.""" |
| 56 json_dict = self.ToJsonDict() | 56 json_dict = self.ToJsonDict() |
| 57 with open(json_path, 'w') as output_file: | 57 with open(json_path, 'w') as output_file: |
| 58 json.dump(json_dict, output_file) | 58 json.dump(json_dict, output_file) |
| 59 | 59 |
| 60 @classmethod | 60 @classmethod |
| 61 def FromJsonDict(cls, json_dict): | 61 def FromJsonDict(cls, json_dict): |
| 62 """Returns an instance from a dictionary returned by ToJsonDict().""" | 62 """Returns an instance from a dictionary returned by ToJsonDict().""" |
| 63 keys = (cls._URL_KEY, cls._METADATA_KEY, cls._PAGE_KEY, cls._REQUEST_KEY, | 63 keys = (cls._URL_KEY, cls._METADATA_KEY, cls._PAGE_KEY, cls._REQUEST_KEY, |
| 64 cls._TRACING_KEY) | 64 cls._TRACING_KEY) |
| 65 assert all(key in json_dict for key in keys) | 65 assert all(key in json_dict for key in keys) |
| 66 page = page_track.PageTrack.FromJsonDict(json_dict[cls._PAGE_KEY]) | 66 page = page_track.PageTrack.FromJsonDict(json_dict[cls._PAGE_KEY]) |
| 67 request = request_track.RequestTrack.FromJsonDict( | 67 request = request_track.RequestTrack.FromJsonDict( |
| 68 json_dict[cls._REQUEST_KEY]) | 68 json_dict[cls._REQUEST_KEY]) |
| 69 tracing_track = tracing.TracingTrack.FromJsonDict( | 69 track = tracing_track.TracingTrack.FromJsonDict( |
| 70 json_dict[cls._TRACING_KEY]) | 70 json_dict[cls._TRACING_KEY]) |
| 71 return LoadingTrace(json_dict[cls._URL_KEY], json_dict[cls._METADATA_KEY], | 71 return LoadingTrace(json_dict[cls._URL_KEY], json_dict[cls._METADATA_KEY], |
| 72 page, request, tracing_track) | 72 page, request, track) |
| 73 | 73 |
| 74 @classmethod | 74 @classmethod |
| 75 def FromJsonFile(cls, json_path): | 75 def FromJsonFile(cls, json_path): |
| 76 """Returns an instance from a json file saved by ToJsonFile().""" | 76 """Returns an instance from a json file saved by ToJsonFile().""" |
| 77 with open(json_path) as input_file: | 77 with open(json_path) as input_file: |
| 78 return cls.FromJsonDict(json.load(input_file)) | 78 return cls.FromJsonDict(json.load(input_file)) |
| 79 | 79 |
| 80 @classmethod | 80 @classmethod |
| 81 def RecordUrlNavigation( | 81 def RecordUrlNavigation( |
| 82 cls, url, connection, chrome_metadata, categories, | 82 cls, url, connection, chrome_metadata, categories, |
| 83 timeout_seconds=devtools_monitor.DEFAULT_TIMEOUT_SECONDS, | 83 timeout_seconds=devtools_monitor.DEFAULT_TIMEOUT_SECONDS, |
| 84 stop_delay_multiplier=0): | 84 stop_delay_multiplier=0): |
| 85 """Create a loading trace by using controller to fetch url. | 85 """Create a loading trace by using controller to fetch url. |
| 86 | 86 |
| 87 Args: | 87 Args: |
| 88 url: (str) url to fetch. | 88 url: (str) url to fetch. |
| 89 connection: An opened devtools connection. | 89 connection: An opened devtools connection. |
| 90 chrome_metadata: Dictionary of chrome metadata. | 90 chrome_metadata: Dictionary of chrome metadata. |
| 91 categories: as in tracing.TracingTrack | 91 categories: as in tracing_track.TracingTrack |
| 92 timeout_seconds: monitoring connection timeout in seconds. | 92 timeout_seconds: monitoring connection timeout in seconds. |
| 93 stop_delay_multiplier: How long to wait after page load completed before | 93 stop_delay_multiplier: How long to wait after page load completed before |
| 94 tearing down, relative to the time it took to reach the page load to | 94 tearing down, relative to the time it took to reach the page load to |
| 95 complete. | 95 complete. |
| 96 | 96 |
| 97 Returns: | 97 Returns: |
| 98 LoadingTrace instance. | 98 LoadingTrace instance. |
| 99 """ | 99 """ |
| 100 page = page_track.PageTrack(connection) | 100 page = page_track.PageTrack(connection) |
| 101 request = request_track.RequestTrack(connection) | 101 request = request_track.RequestTrack(connection) |
| 102 trace = tracing.TracingTrack(connection, categories) | 102 trace = tracing_track.TracingTrack(connection, categories) |
| 103 start_date_str = datetime.datetime.utcnow().isoformat() | 103 start_date_str = datetime.datetime.utcnow().isoformat() |
| 104 seconds_since_epoch=time.time() | 104 seconds_since_epoch=time.time() |
| 105 connection.MonitorUrl(url, | 105 connection.MonitorUrl(url, |
| 106 timeout_seconds=timeout_seconds, | 106 timeout_seconds=timeout_seconds, |
| 107 stop_delay_multiplier=stop_delay_multiplier) | 107 stop_delay_multiplier=stop_delay_multiplier) |
| 108 trace = cls(url, chrome_metadata, page, request, trace) | 108 trace = cls(url, chrome_metadata, page, request, trace) |
| 109 trace.metadata.update(date=start_date_str, | 109 trace.metadata.update(date=start_date_str, |
| 110 seconds_since_epoch=seconds_since_epoch) | 110 seconds_since_epoch=seconds_since_epoch) |
| 111 return trace | 111 return trace |
| 112 | 112 |
| 113 @property | 113 @property |
| 114 def tracing_track(self): | 114 def tracing_track(self): |
| 115 if not self._tracing_track: | 115 if not self._tracing_track: |
| 116 self._RestoreTracingTrack() | 116 self._RestoreTracingTrack() |
| 117 return self._tracing_track | 117 return self._tracing_track |
| 118 | 118 |
| 119 def Slim(self): | 119 def Slim(self): |
| 120 """Slims the memory usage of a trace by dropping the TraceEvents from it. | 120 """Slims the memory usage of a trace by dropping the TraceEvents from it. |
| 121 | 121 |
| 122 The tracing track is restored on-demand when accessed. | 122 The tracing track is restored on-demand when accessed. |
| 123 """ | 123 """ |
| 124 self._tracing_json_str = json.dumps(self._tracing_track.ToJsonDict()) | 124 self._tracing_json_str = json.dumps(self._tracing_track.ToJsonDict()) |
| 125 self._tracing_track = None | 125 self._tracing_track = None |
| 126 | 126 |
| 127 def _RestoreTracingTrack(self): | 127 def _RestoreTracingTrack(self): |
| 128 if not self._tracing_json_str: | 128 if not self._tracing_json_str: |
| 129 return None | 129 return None |
| 130 self._tracing_track = tracing.TracingTrack.FromJsonDict( | 130 self._tracing_track = tracing_track.TracingTrack.FromJsonDict( |
| 131 json.loads(self._tracing_json_str)) | 131 json.loads(self._tracing_json_str)) |
| 132 self._tracing_json_str = None | 132 self._tracing_json_str = None |
| OLD | NEW |