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 """The request data track. | 5 """The request data track. |
6 | 6 |
7 When executed, parses a JSON dump of DevTools messages. | 7 When executed, parses a JSON dump of DevTools messages. |
8 """ | 8 """ |
9 | 9 |
10 import bisect | 10 import bisect |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 from_service_worker: (bool) Whether the request was served by a Service | 168 from_service_worker: (bool) Whether the request was served by a Service |
169 Worker. | 169 Worker. |
170 timing: (Timing) Request timing, extended with loading_finished. | 170 timing: (Timing) Request timing, extended with loading_finished. |
171 status: (int) Response status code. | 171 status: (int) Response status code. |
172 status_text: (str) Response status text received in the status line. | 172 status_text: (str) Response status text received in the status line. |
173 encoded_data_length: (int) Total encoded data length. | 173 encoded_data_length: (int) Total encoded data length. |
174 data_chunks: (list) [(offset, encoded_data_length), ...] List of data | 174 data_chunks: (list) [(offset, encoded_data_length), ...] List of data |
175 chunks received, with their offset in ms relative to | 175 chunks received, with their offset in ms relative to |
176 Timing.requestTime. | 176 Timing.requestTime. |
177 failed: (bool) Whether the request failed. | 177 failed: (bool) Whether the request failed. |
| 178 error_text: (str) User friendly error message when request failed. |
178 start_msec: (float) Request start time, in milliseconds from chrome start. | 179 start_msec: (float) Request start time, in milliseconds from chrome start. |
179 end_msec: (float) Request end time, in milliseconds from chrome start. | 180 end_msec: (float) Request end time, in milliseconds from chrome start. |
180 start_msec. | 181 start_msec. |
181 """ | 182 """ |
182 REQUEST_PRIORITIES = ('VeryLow', 'Low', 'Medium', 'High', 'VeryHigh') | 183 REQUEST_PRIORITIES = ('VeryLow', 'Low', 'Medium', 'High', 'VeryHigh') |
183 RESOURCE_TYPES = ('Document', 'Stylesheet', 'Image', 'Media', 'Font', | 184 RESOURCE_TYPES = ('Document', 'Stylesheet', 'Image', 'Media', 'Font', |
184 'Script', 'TextTrack', 'XHR', 'Fetch', 'EventSource', | 185 'Script', 'TextTrack', 'XHR', 'Fetch', 'EventSource', |
185 'WebSocket', 'Manifest', 'Other') | 186 'WebSocket', 'Manifest', 'Other') |
186 INITIATORS = ('parser', 'script', 'other', 'redirect') | 187 INITIATORS = ('parser', 'script', 'other', 'redirect') |
187 INITIATING_REQUEST = 'initiating_request' | 188 INITIATING_REQUEST = 'initiating_request' |
(...skipping 16 matching lines...) Expand all Loading... |
204 self.resource_type = None | 205 self.resource_type = None |
205 self.served_from_cache = False | 206 self.served_from_cache = False |
206 self.from_disk_cache = False | 207 self.from_disk_cache = False |
207 self.from_service_worker = False | 208 self.from_service_worker = False |
208 self.timing = None | 209 self.timing = None |
209 self.status = None | 210 self.status = None |
210 self.status_text = None | 211 self.status_text = None |
211 self.encoded_data_length = 0 | 212 self.encoded_data_length = 0 |
212 self.data_chunks = [] | 213 self.data_chunks = [] |
213 self.failed = False | 214 self.failed = False |
| 215 self.error_text = None |
214 | 216 |
215 @property | 217 @property |
216 def start_msec(self): | 218 def start_msec(self): |
217 return self.timing.request_time * 1000 | 219 return self.timing.request_time * 1000 |
218 | 220 |
219 @property | 221 @property |
220 def end_msec(self): | 222 def end_msec(self): |
221 if self.start_msec is None: | 223 if self.start_msec is None: |
222 return None | 224 return None |
223 return self.start_msec + self.timing.LargestOffset() | 225 return self.start_msec + self.timing.LargestOffset() |
(...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
742 r.request_id = '%s%s.%d' % (request_id, self._REDIRECT_SUFFIX, | 744 r.request_id = '%s%s.%d' % (request_id, self._REDIRECT_SUFFIX, |
743 redirect_index + 1) | 745 redirect_index + 1) |
744 initiator = { | 746 initiator = { |
745 'type': 'redirect', Request.INITIATING_REQUEST: r.request_id} | 747 'type': 'redirect', Request.INITIATING_REQUEST: r.request_id} |
746 self._requests_in_flight[r.request_id] = (r, RequestTrack._STATUS_FINISHED) | 748 self._requests_in_flight[r.request_id] = (r, RequestTrack._STATUS_FINISHED) |
747 del self._requests_in_flight[request_id] | 749 del self._requests_in_flight[request_id] |
748 self._FinalizeRequest(r.request_id) | 750 self._FinalizeRequest(r.request_id) |
749 return initiator | 751 return initiator |
750 | 752 |
751 def _RequestServedFromCache(self, request_id, _): | 753 def _RequestServedFromCache(self, request_id, _): |
752 assert request_id in self._requests_in_flight | 754 if request_id not in self._requests_in_flight: |
| 755 return |
753 (request, status) = self._requests_in_flight[request_id] | 756 (request, status) = self._requests_in_flight[request_id] |
754 assert status == RequestTrack._STATUS_SENT | 757 assert status == RequestTrack._STATUS_SENT |
755 request.served_from_cache = True | 758 request.served_from_cache = True |
756 | 759 |
757 def _ResponseReceived(self, request_id, params): | 760 def _ResponseReceived(self, request_id, params): |
758 assert request_id in self._requests_in_flight | 761 assert request_id in self._requests_in_flight |
759 (r, status) = self._requests_in_flight[request_id] | 762 (r, status) = self._requests_in_flight[request_id] |
760 if status == RequestTrack._STATUS_RESPONSE: | 763 if status == RequestTrack._STATUS_RESPONSE: |
761 # Duplicated messages (apart from the timestamp) are OK. | 764 # Duplicated messages (apart from the timestamp) are OK. |
762 old_params = self._request_id_to_response_received[request_id] | 765 old_params = self._request_id_to_response_received[request_id] |
(...skipping 26 matching lines...) Expand all Loading... |
789 # TODO(droger): the timestamp is inacurate, get the real timings instead. | 792 # TODO(droger): the timestamp is inacurate, get the real timings instead. |
790 if not response.get('timing') or r.served_from_cache: | 793 if not response.get('timing') or r.served_from_cache: |
791 timing_dict = {'requestTime': r.timestamp} | 794 timing_dict = {'requestTime': r.timestamp} |
792 else: | 795 else: |
793 timing_dict = response['timing'] | 796 timing_dict = response['timing'] |
794 r.timing = Timing.FromDevToolsDict(timing_dict) | 797 r.timing = Timing.FromDevToolsDict(timing_dict) |
795 self._requests_in_flight[request_id] = (r, RequestTrack._STATUS_RESPONSE) | 798 self._requests_in_flight[request_id] = (r, RequestTrack._STATUS_RESPONSE) |
796 self._request_id_to_response_received[request_id] = params | 799 self._request_id_to_response_received[request_id] = params |
797 | 800 |
798 def _DataReceived(self, request_id, params): | 801 def _DataReceived(self, request_id, params): |
| 802 if request_id not in self._requests_in_flight: |
| 803 return |
799 (r, status) = self._requests_in_flight[request_id] | 804 (r, status) = self._requests_in_flight[request_id] |
800 assert (status == RequestTrack._STATUS_RESPONSE | 805 assert (status == RequestTrack._STATUS_RESPONSE |
801 or status == RequestTrack._STATUS_DATA) | 806 or status == RequestTrack._STATUS_DATA) |
802 offset = r._TimestampOffsetFromStartMs(params['timestamp']) | 807 offset = r._TimestampOffsetFromStartMs(params['timestamp']) |
803 r.data_chunks.append((offset, params['encodedDataLength'])) | 808 r.data_chunks.append((offset, params['encodedDataLength'])) |
804 self._requests_in_flight[request_id] = (r, RequestTrack._STATUS_DATA) | 809 self._requests_in_flight[request_id] = (r, RequestTrack._STATUS_DATA) |
805 | 810 |
806 def _LoadingFinished(self, request_id, params): | 811 def _LoadingFinished(self, request_id, params): |
807 assert request_id in self._requests_in_flight | 812 if request_id not in self._requests_in_flight: |
| 813 return |
808 (r, status) = self._requests_in_flight[request_id] | 814 (r, status) = self._requests_in_flight[request_id] |
809 assert (status == RequestTrack._STATUS_RESPONSE | 815 assert (status == RequestTrack._STATUS_RESPONSE |
810 or status == RequestTrack._STATUS_DATA) | 816 or status == RequestTrack._STATUS_DATA) |
811 r.encoded_data_length = params['encodedDataLength'] | 817 r.encoded_data_length = params['encodedDataLength'] |
812 r.timing.loading_finished = r._TimestampOffsetFromStartMs( | 818 r.timing.loading_finished = r._TimestampOffsetFromStartMs( |
813 params['timestamp']) | 819 params['timestamp']) |
814 self._requests_in_flight[request_id] = (r, RequestTrack._STATUS_FINISHED) | 820 self._requests_in_flight[request_id] = (r, RequestTrack._STATUS_FINISHED) |
815 self._FinalizeRequest(request_id) | 821 self._FinalizeRequest(request_id) |
816 | 822 |
817 def _LoadingFailed(self, request_id, _): | 823 def _LoadingFailed(self, request_id, params): |
818 if request_id not in self._requests_in_flight: | 824 if request_id not in self._requests_in_flight: |
819 logging.warning('An unknown request failed: %s' % request_id) | 825 logging.warning('An unknown request failed: %s' % request_id) |
820 return | 826 return |
821 (r, _) = self._requests_in_flight[request_id] | 827 (r, _) = self._requests_in_flight[request_id] |
822 r.failed = True | 828 r.failed = True |
| 829 r.error_text = params['errorText'] |
823 self._requests_in_flight[request_id] = (r, RequestTrack._STATUS_FINISHED) | 830 self._requests_in_flight[request_id] = (r, RequestTrack._STATUS_FINISHED) |
824 self._FinalizeRequest(request_id) | 831 self._FinalizeRequest(request_id) |
825 | 832 |
826 def _FinalizeRequest(self, request_id): | 833 def _FinalizeRequest(self, request_id): |
827 assert request_id in self._requests_in_flight | 834 if request_id not in self._requests_in_flight: |
| 835 return |
828 (request, status) = self._requests_in_flight[request_id] | 836 (request, status) = self._requests_in_flight[request_id] |
829 assert status == RequestTrack._STATUS_FINISHED | 837 assert status == RequestTrack._STATUS_FINISHED |
830 del self._requests_in_flight[request_id] | 838 del self._requests_in_flight[request_id] |
831 self._completed_requests_by_id[request_id] = request | 839 self._completed_requests_by_id[request_id] = request |
832 self._requests.append(request) | 840 self._requests.append(request) |
833 | 841 |
834 def __eq__(self, o): | 842 def __eq__(self, o): |
835 return self._requests == o._requests | 843 return self._requests == o._requests |
836 | 844 |
837 | 845 |
(...skipping 13 matching lines...) Expand all Loading... |
851 | 859 |
852 | 860 |
853 if __name__ == '__main__': | 861 if __name__ == '__main__': |
854 import json | 862 import json |
855 import sys | 863 import sys |
856 events = json.load(open(sys.argv[1], 'r')) | 864 events = json.load(open(sys.argv[1], 'r')) |
857 request_track = RequestTrack(None) | 865 request_track = RequestTrack(None) |
858 for event in events: | 866 for event in events: |
859 event_method = event['method'] | 867 event_method = event['method'] |
860 request_track.Handle(event_method, event) | 868 request_track.Handle(event_method, event) |
OLD | NEW |