Changeset 193870 in webkit
- Timestamp:
- Dec 9, 2015 2:45:21 PM (8 years ago)
- Location:
- trunk/Source/WebInspectorUI
- Files:
-
- 2 added
- 4 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebInspectorUI/ChangeLog
r193858 r193870 1 2015-12-09 Brian Burg <bburg@apple.com> 2 3 Web Inspector: control whether to collect and dump protocol messages using a WebInspector.Setting 4 https://bugs.webkit.org/show_bug.cgi?id=151635 5 6 Reviewed by Timothy Hatcher. 7 8 When closing and reopening the inspector, the setting for whether 9 to dump protocol messages should be persisted. Otherwise, enabling 10 dumping from the debug-only UI will miss the initial flood of 11 messages that are processed when the Inspector loads initial data. 12 13 To support a persistent setting, and build some infrastructure for 14 more advanced uses of collected protocol messages, this patch adds 15 a new object to trace protocol events. It gets callbacks for each 16 and implements the console-dumping functionality previously baked in 17 to InspectorBackend. 18 19 In follow-up patches, other protocol tracers will be added to save 20 protocol data to disk, marshall it to a higher inspection level, 21 or provide more fine-grained control over what is logged. 22 23 This change moves Setting.js into the Base/ directory, 24 since it is used by Views, Models, and now Protocol classes. 25 26 * UserInterface/Base/Setting.js: Renamed from Source/WebInspectorUI/UserInterface/Models/Setting.js. 27 (WebInspector.Setting): 28 (WebInspector.Setting.prototype.get name): 29 (WebInspector.Setting.prototype.get value): 30 (WebInspector.Setting.prototype.set value): 31 * UserInterface/Main.html: 32 * UserInterface/Protocol/InspectorBackend.js: 33 (InspectorBackendClass): 34 (InspectorBackendClass.prototype.set dumpInspectorProtocolMessages): 35 (InspectorBackendClass.prototype.get dumpInspectorProtocolMessages): 36 37 We still want to support the legacy way to enable dumping: 38 `InspectorBackend.dumpInspectorProtocolMessages = true`. This 39 is because some tests always use it, and it's easier to set this 40 flag in a custom Bootstrap.js file than to configure the Setting. 41 42 (InspectorBackendClass.prototype.set dumpInspectorTimeStats): 43 (InspectorBackendClass.prototype.get dumpInspectorTimeStats): 44 45 We still want to support the legacy way to enable dumping: 46 `InspectorBackend.dumpInspectorTimeStats = true`. This is 47 because MessageDispatcher checks this flag for its logging. 48 49 (InspectorBackendClass.prototype.set activeTracer): 50 (InspectorBackendClass.prototype.get activeTracer): 51 52 Set the active tracer, finalizing and removing any active tracer 53 if one exists. If removing a custom tracer (setting to null), then 54 re-sync activeTracer with the automatic tracing Setting. 55 56 (InspectorBackendClass.prototype.dispatch): 57 (InspectorBackendClass.prototype._startOrStopAutomaticTracing): 58 59 Sync the Setting with activeTracer. If an custom tracer is active, 60 don't replace it with the automatic logging tracer. 61 62 (InspectorBackendClass.prototype._sendCommandToBackendWithCallback): 63 (InspectorBackendClass.prototype._sendCommandToBackendExpectingPromise): 64 (InspectorBackendClass.prototype._sendMessageToBackend): 65 (InspectorBackendClass.prototype._dispatchResponse): 66 (InspectorBackendClass.prototype._dispatchEvent): 67 (InspectorBackendClass.prototype._flushPendingScripts): 68 * UserInterface/Protocol/LoggingProtocolTracer.js: Added. 69 (WebInspector.LoggingProtocolTracer): 70 (WebInspector.LoggingProtocolTracer.prototype.set dumpMessagesToConsole): 71 (WebInspector.LoggingProtocolTracer.prototype.get dumpMessagesToConsole): 72 (WebInspector.LoggingProtocolTracer.prototype.set dumpTimingDataToConsole): 73 (WebInspector.LoggingProtocolTracer.prototype.get dumpTimingDataToConsole): 74 (WebInspector.LoggingProtocolTracer.prototype.logFrontendException): 75 (WebInspector.LoggingProtocolTracer.prototype.logProtocolError): 76 (WebInspector.LoggingProtocolTracer.prototype.logFrontendRequest): 77 (WebInspector.LoggingProtocolTracer.prototype.logWillHandleResponse): 78 (WebInspector.LoggingProtocolTracer.prototype.logDidHandleResponse): 79 (WebInspector.LoggingProtocolTracer.prototype.logWillHandleEvent): 80 (WebInspector.LoggingProtocolTracer.prototype.logDidHandleEvent): 81 (WebInspector.LoggingProtocolTracer.prototype._processEntry): 82 * UserInterface/Protocol/ProtocolTracer.js: Added. 83 (WebInspector.ProtocolTracer.prototype.logStarted): 84 (WebInspector.ProtocolTracer.prototype.logFrontendException): 85 (WebInspector.ProtocolTracer.prototype.logProtocolError): 86 (WebInspector.ProtocolTracer.prototype.logFrontendRequest): 87 (WebInspector.ProtocolTracer.prototype.logWillHandleResponse): 88 (WebInspector.ProtocolTracer.prototype.logDidHandleResponse): 89 (WebInspector.ProtocolTracer.prototype.logWillHandleEvent): 90 (WebInspector.ProtocolTracer.prototype.logDidHandleEvent): (WebInspector.ProtocolTracer.prototype.logFinished): 91 (WebInspector.ProtocolTracer): 92 * UserInterface/Test.html: 93 1 94 2015-12-09 Brian Burg <bburg@apple.com> 2 95 -
trunk/Source/WebInspectorUI/UserInterface/Base/Setting.js
r193867 r193870 38 38 this._name = name; 39 39 40 let inspectionLevel = InspectorFrontendHost .inspectionLevel();40 let inspectionLevel = InspectorFrontendHost ? InspectorFrontendHost.inspectionLevel() : 1; 41 41 let levelString = inspectionLevel > 1 ? "-" + inspectionLevel : ""; 42 42 this._localStorageKey = `com.apple.WebInspector${levelString}.${name}`; -
trunk/Source/WebInspectorUI/UserInterface/Main.html
r193646 r193870 225 225 <script src="Base/URLUtilities.js"></script> 226 226 <script src="Base/Utilities.js"></script> 227 <script src="Base/Setting.js"></script> 228 229 <script src="Protocol/ProtocolTracer.js"></script> 230 <script src="Protocol/LoggingProtocolTracer.js"></script> 227 231 228 232 <script src="Protocol/ApplicationCacheObserver.js"></script> … … 329 333 <script src="Models/ScriptSyntaxTree.js"></script> 330 334 <script src="Models/ScriptTimelineRecord.js"></script> 331 <script src="Models/Setting.js"></script>332 335 <script src="Models/SourceCodePosition.js"></script> 333 336 <script src="Models/SourceCodeRevision.js"></script> -
trunk/Source/WebInspectorUI/UserInterface/Protocol/InspectorBackend.js
r190839 r193870 39 39 this._agents = {}; 40 40 this._deferredScripts = []; 41 42 this.dumpInspectorTimeStats = false; 43 this.dumpInspectorProtocolMessages = false; 44 this.warnForLongMessageHandling = false; 45 this.longMessageHandlingThreshold = 10; // milliseconds. 46 47 this._log = window.InspectorTest ? InspectorFrontendHost.unbufferedLog.bind(InspectorFrontendHost) : console.log.bind(console); 41 this._activeTracer = null; 42 this._automaticTracer = null; 43 44 this._dumpInspectorTimeStats = false; 45 46 let setting = WebInspector.autoLogProtocolMessagesSetting = new WebInspector.Setting("auto-collect-protocol-messages", false); 47 setting.addEventListener(WebInspector.Setting.Event.Changed, this._startOrStopAutomaticTracing.bind(this)) 48 this._startOrStopAutomaticTracing(); 48 49 } 49 50 50 51 // Public 52 53 // It's still possible to set this flag on InspectorBackend to just 54 // dump protocol traffic as it happens. For more complex uses of 55 // protocol data, install a subclass of WebInspector.ProtocolTracer. 56 set dumpInspectorProtocolMessages(value) 57 { 58 // Implicitly cause automatic logging to start if it's allowed. 59 let setting = WebInspector.autoLogProtocolMessagesSetting; 60 setting.value = value; 61 62 if (this.activeTracer !== this._automaticTracer) 63 return; 64 65 if (this.activeTracer) 66 this.activeTracer.dumpMessagesToConsole = value; 67 } 68 69 get dumpInspectorProtocolMessages() 70 { 71 return !!this._automaticTracer; 72 } 73 74 set dumpInspectorTimeStats(value) 75 { 76 if (!this.dumpInspectorProtocolMessages) 77 this.dumpInspectorProtocolMessages = true; 78 79 if (this.activeTracer !== this._automaticTracer) 80 return; 81 82 if (this.activeTracer) 83 this.activeTracer.dumpTimingDataToConsole = value; 84 } 85 86 get dumpInspectorTimeStats() 87 { 88 return this._dumpInspectorTimeStats; 89 } 90 91 set activeTracer(tracer) 92 { 93 console.assert(!tracer || tracer instanceof WebInspector.ProtocolTracer); 94 95 // Bail early if no state change is to be made. 96 if (!tracer && !this._activeTracer) 97 return; 98 99 if (tracer === this._activeTracer) 100 return; 101 102 // Don't allow an automatic tracer to dislodge a custom tracer. 103 if (this._activeTracer && tracer === this._automaticTracer) 104 return; 105 106 if (this.activeTracer) 107 this.activeTracer.logFinished(); 108 109 if (this._activeTracer === this._automaticTracer) 110 this._automaticTracer = null; 111 112 this._activeTracer = tracer; 113 if (this.activeTracer) 114 this.activeTracer.logStarted(); 115 else { 116 // If the custom tracer was removed and automatic tracing is enabled, 117 // then create a new automatic tracer and install it in its place. 118 this._startOrStopAutomaticTracing(); 119 } 120 } 121 122 get activeTracer() 123 { 124 return this._activeTracer || null; 125 } 51 126 52 127 registerCommand(qualifiedName, callSignature, replySignature) … … 79 154 dispatch(message) 80 155 { 81 if (this.dumpInspectorProtocolMessages) 82 this._log("backend: " + ((typeof message === "string") ? message : JSON.stringify(message))); 83 84 var messageObject = (typeof message === "string") ? JSON.parse(message) : message; 156 let messageObject = (typeof message === "string") ? JSON.parse(message) : message; 85 157 86 158 if ("id" in messageObject) … … 114 186 // Private 115 187 188 _startOrStopAutomaticTracing() 189 { 190 let setting = WebInspector.autoLogProtocolMessagesSetting; 191 192 // Bail if there is no state transition to be made. 193 if (!(setting.value ^ !!this.activeTracer)) 194 return; 195 196 if (!setting.value) { 197 if (this.activeTracer === this._automaticTracer) 198 this.activeTracer = null; 199 200 this._automaticTracer = null; 201 } else { 202 this._automaticTracer = new WebInspector.LoggingProtocolTracer; 203 this._automaticTracer.dumpMessagesToConsole = this.dumpInspectorProtocolMessages; 204 this._automaticTracer.dumpTimingDataToConsole = this.dumpTimingDataToConsole; 205 // This will be ignored if a custom tracer is installed. 206 this.activeTracer = this._automaticTracer; 207 } 208 } 209 116 210 _agentForDomain(domainName) 117 211 { … … 138 232 let responseData = {command, callback}; 139 233 140 if (this. dumpInspectorTimeStats)234 if (this.activeTracer) 141 235 responseData.sendRequestTimestamp = timestamp(); 142 236 … … 159 253 let responseData = {command}; 160 254 161 if (this. dumpInspectorTimeStats)255 if (this.activeTracer) 162 256 responseData.sendRequestTimestamp = timestamp(); 163 257 … … 175 269 { 176 270 let stringifiedMessage = JSON.stringify(messageObject); 177 if (this. dumpInspectorProtocolMessages)178 this. _log("frontend: " +stringifiedMessage);271 if (this.activeTracer) 272 this.activeTracer.logFrontendRequest(stringifiedMessage); 179 273 180 274 InspectorFrontendHost.sendMessageToBackend(stringifiedMessage); … … 196 290 let {command, callback, promise} = responseData; 197 291 198 varprocessingStartTimestamp;199 if (this. dumpInspectorTimeStats)292 let processingStartTimestamp; 293 if (this.activeTracer) { 200 294 processingStartTimestamp = timestamp(); 295 this.activeTracer.logWillHandleResponse(JSON.stringify(messageObject)); 296 } 201 297 202 298 if (typeof callback === "function") … … 207 303 console.error("Received a command response without a corresponding callback or promise.", messageObject, command); 208 304 209 let processingDuration = (timestamp() - processingStartTimestamp).toFixed(3); 210 if (this.warnForLongMessageHandling && processingDuration > this.longMessageHandlingThreshold) 211 console.warn(`InspectorBackend: took ${processingDuration}ms to handle response for command: ${command.qualifiedName}`); 212 213 if (this.dumpInspectorTimeStats) { 214 let roundTripDuration = (processingStartTimestamp - responseData.sendRequestTimestamp).toFixed(3); 215 console.log(`time-stats: Handling: ${processingDuration}ms; RTT: ${roundTripDuration}ms; (command ${command.qualifiedName})`); 305 if (this.activeTracer) { 306 let processingTime = (timestamp() - processingStartTimestamp).toFixed(3); 307 let roundTripTime = (processingStartTimestamp - responseData.sendRequestTimestamp).toFixed(3); 308 this.activeTracer.logDidHandleResponse(JSON.stringify(messageObject), {rtt: roundTripTime, dispatch: processingTime}); 216 309 } 217 310 … … 248 341 _dispatchEvent(messageObject) 249 342 { 250 varqualifiedName = messageObject["method"];251 var[domainName, eventName] = qualifiedName.split(".");343 let qualifiedName = messageObject["method"]; 344 let [domainName, eventName] = qualifiedName.split("."); 252 345 if (!(domainName in this._agents)) { 253 346 console.error("Protocol Error: Attempted to dispatch method '" + eventName + "' for non-existing domain '" + domainName + "'"); … … 255 348 } 256 349 257 varagent = this._agentForDomain(domainName);350 let agent = this._agentForDomain(domainName); 258 351 if (!agent.active) { 259 352 console.error("Protocol Error: Attempted to dispatch method for domain '" + domainName + "' which exists but is not active."); … … 261 354 } 262 355 263 varevent = agent.getEvent(eventName);356 let event = agent.getEvent(eventName); 264 357 if (!event) { 265 358 console.error("Protocol Error: Attempted to dispatch an unspecified method '" + qualifiedName + "'"); … … 267 360 } 268 361 269 var eventArguments = []; 270 if (messageObject["params"]) { 271 var parameterNames = event.parameterNames; 272 for (var i = 0; i < parameterNames.length; ++i) 273 eventArguments.push(messageObject["params"][parameterNames[i]]); 274 } 275 276 var processingStartTimestamp; 277 if (this.dumpInspectorTimeStats) 362 let eventArguments = []; 363 if (messageObject["params"]) 364 eventArguments = event.parameterNames.map((name) => messageObject["params"][name]); 365 366 let processingStartTimestamp; 367 if (this.activeTracer) { 278 368 processingStartTimestamp = timestamp(); 369 this.activeTracer.logWillHandleEvent(JSON.stringify(messageObject)); 370 } 279 371 280 372 try { … … 282 374 } catch (e) { 283 375 console.error("Uncaught exception in inspector page while handling event " + qualifiedName, e); 284 }285 286 let processingDuration = (timestamp() - processingStartTimestamp).toFixed(3);287 if (this.warnForLongMessageHandling && processingDuration > this.longMessageHandlingThreshold) 288 console.warn(`InspectorBackend: took ${processingDuration}ms to handle event: ${messageObject.method}`);289 290 if (this.dumpInspectorTimeStats)291 console.log(`time-stats: Handling: ${processingDuration}ms (event ${messageObject.method})`);376 if (this.activeTracer) 377 this.activeTracer.logFrontendException(JSON.stringify(messageObject), e); 378 } 379 380 if (this.activeTracer) { 381 let processingTime = (timestamp() - processingStartTimestamp).toFixed(3); 382 this.activeTracer.logDidHandleEvent(JSON.stringify(messageObject), {dispatch: processingTime}); 383 } 292 384 } 293 385 … … 301 393 console.assert(this._pendingResponses.size === 0); 302 394 303 varscriptsToRun = this._deferredScripts;395 let scriptsToRun = this._deferredScripts; 304 396 this._deferredScripts = []; 305 for ( varscript of scriptsToRun)397 for (let script of scriptsToRun) 306 398 script.call(this); 307 399 } -
trunk/Source/WebInspectorUI/UserInterface/Test.html
r192906 r193870 50 50 <script src="Base/URLUtilities.js"></script> 51 51 <script src="Base/Utilities.js"></script> 52 <script src="Base/Setting.js"></script> 53 54 <script src="Protocol/ProtocolTracer.js"></script> 55 <script src="Protocol/LoggingProtocolTracer.js"></script> 52 56 53 57 <script src="Protocol/InspectorBackend.js"></script> … … 136 140 <script src="Models/ScriptSyntaxTree.js"></script> 137 141 <script src="Models/ScriptTimelineRecord.js"></script> 138 <script src="Models/Setting.js"></script>139 142 <script src="Models/SourceCodeLocation.js"></script> 140 143 <script src="Models/SourceCodeRevision.js"></script>
Note: See TracChangeset
for help on using the changeset viewer.