Profiling JavaScript with Spy-js
Spy-js is a tool for debugging, tracing, and profiling JavaScript running on different platforms/browsers/devices as well as server-side Node.js applications. Spy-js recognizes source maps so you can trace applications with CoffeeScript and TypeScript code. For more information, refer to Debugging CoffeeScript and File Watchers.
With PyCharm, you can trace your applications during a SpyJS-specific debugging session and explore the results in the dedicated UI.
To trace a script, Spy-js modifies it on the fly by inserting instrumentation instructions that report back to Spy-js UI about what functions have been invoked when the script executes.
Spy-js uses different mechanisms for tracing Web applications and Node.js applications.
To modify website scripts, Spy-js has to act as a proxy server that "sits" between your browser and the website you are tracing. When you open a traced website in your browser, Spy-js receives the script request, requests the script from your website, receives the script, makes the required modifications, and sends it back to your browser where the script executes, and sends the runtime information to the Spy-js UI.
In case of a Node.js application, Spy-js cannot get between the Node.js server and the scripts if the application is already running. Therefore to trace a Node.js application, spy-js launches the Node.js server and the application itself. This enables Spy-js to intercept and modify script requests and scripts, whereupon the tracing procedure runs as when tracing a website script.
Before you start
Make sure you have Node.js on your computer.
Install and enable the Spy-js plugin on the Settings | Plugins page, tab Marketplace, as described in Installing plugins from JetBrains Marketplace.
Spy-js UI
All the tracing-related activities, such as viewing captured events, examining their call stacks, navigating to the source code, and so on are performed in the dedicated Spy-js Tool Window, in particular in its Trace Run Tab. The tab consists of a toolbar and three panes:
Events Pane
The pane shows a tree of captured events. The top-level nodes represent documents that are Web pages involved in tracing. When you hover over a document, PyCharm displays a tooltip with the URL address of the document, the browser in which it is opened, and the operating system the browser is running on. The document node is also supplied with an icon that indicates the browser in which it is opened.
Under each document node, events detected on the page and scripts started from it are listed. Events of the same type are grouped into visual containers. The header of a container displays the name of the events grouped in it, the average execution time across all the events within the container, and the number of events inside the container. You can expand each node and inspect the individual events in it.
Script file names have different color indicators that help to distinguish between them when working with the Event Stack pane. By hovering your mouse over a script filename, you can see the full script URL.
Once an event is clicked, its call stack is displayed in the Event Stack pane. The stack is represented by a tree of function calls.
Event Stack Pane
Once an event in the Events pane is clicked, its call stack is displayed in the Event Stack pane. The stack is represented by a tree of function calls. Each tree node represents the invoked function. Node text contains the total execution time, the script filename and the function name. When you click a node, the Quick Evaluation pane shows additional function call details, parameter values and return value, occurred exception details if there was one during the function execution.
The pane is synchronized with the editor, so you can navigate from an item in the stack tree to the corresponding trace file or source file.
A trace file is a write-protected prettified version of a script and is named <script name>.js.trace. When you double-click an item in the stack tree or select it and choose Jump to Trace from the context menu of the selection, the corresponding trace file opens in the editor with the caret placed at the clicked function. Another approach is to press the Autoscroll to Trace toggle button and select various stack nodes. In this case, the trace file opens when you click an event or script in the Events pane.
You can not only jump to a function but also to the place in the code where it was called from. To do that, select the required item and choose Jump to Caller from the context menu.
The contents of the file are highlighted to display the code execution path of the selected stack node.
When you are tracing an application with ECMASript6, CoffeeScript, and TypeScript code, Spy-js also generates mapped trace files. These are EcmaScript 6, TypeScript, or CoffeeScript trace files with the extensions .ts.trace, .coffee.trace, or .js.trace. The fragments of code in these files are highlighted as if they were really executed.
You can also navigate to the source file displayed as is, without prettifying, by selecting an item in the Event Stack pane and choosing Jump to Source from the context menu of the selection. If the traced site is mapped with a PyCharm project, PyCharm detects the corresponding local file according to the mapping and opens this file in the editor. If you are tracing a site that is not mapped to a PyCharm project, PyCharm opens the read-only page source, just as if you chose View Page Source in the browser.
When the traced site is mapped with a PyCharm project, PyCharm opens the source file on any attempt to edit the opened trace file.
Quick Evaluation Pane
When you click a node in the Event Stack pane, the Quick Evaluation pane shows additional function call details, parameter values and return value, occurred exception details if there was one during the function execution.
Starting a Spy-js tracing session
From PyCharm, Spy-js is started with a run/debug configuration of the type Spy-js for tracing Web applications or of the type Spy-js for Node.js for tracing Node.js applications.
To create a Spy-js debug configuration
Go to Edit Configurations from the Run widget on the toolbar.
. Alternatively, selectIn the Edit Configurations dialog that opens, click the Add button () on the toolbar and select Spy-js from the list.
The Run/Debug Configuration: Spy-js dialog opens.
Specify the Node.js interpreter to use.
The trace server port is filled in automatically. To avoid port conflicts, it is recommended that you accept the suggested value and keep the Automatically configure system proxy checkbox selected. As a result, the specified port number is automatically set for the system proxy server.
Alternatively, configure your system proxy port manually.
Go to Use a proxy server. In the Port field, type the trace server port number.
and turn onLearn more from the Microsoft official website.
Go to Advanced, switch to the Proxies tab, clear the Automatic Proxy Configuration, and type the URL address of your Proxy configuration file. Make sure, the port in the URL is the same as the trace server port from your run/debug configuration.
, clickLearn more from the Apple official website.
From the Use list, select the way to specify the way to configure a tracing session.
To have Spy-js apply its internal predefined configuration, choose Default configuration.
To have your custom manually created configuration applied, choose the Configuration file option and then specify the location of your custom configuration file in the Configuration field below.
A configuration file is a JavaScript file with the extension .js or .conf.js that contains valid JavaScript code that meets the Spy-js configuration requirements. If PyCharm detects files with the extension .conf.js in the project, these files are displayed in the list.
Type the path to the configuration file manually or click Browse and choose the location in the dialog that opens. Once specified, a configuration file is added to the list so you can get if next time from the list instead of specifying the path.
To start tracing a Web application
Choose the newly created configuration in the Select run/debug configuration list on the toolbar and click . The Spy-js Tool Window opens with an empty Trace Run tab and a Trace Proxy Server tab informing you about the status of the proxy server.
Switch to the browser and refresh the page to start debugging from. Spy-js starts capturing events on this page and the Spy-js tool window shows them in the Events pane.
To create a Spy-js for Node.js debug configuration
Go to Edit Configurations from the Run widget on the toolbar.
. Alternatively, selectIn the Edit Configurations dialog that opens, click the Add button () on the toolbar and select Spy-js for Node.js from the list.
The Run/Debug Configuration: Spy-js for Node.js dialog opens.
Specify the Node.js interpreter to use.
If you choose the Project alias, PyCharm will automatically use the project default interpreter from the Node interpreter field on the Node.js page . In most cases, PyCharm detects the project default interpreter and fills in the field itself.
You can also choose another configured local or remote interpreter or click and configure a new one.
Specify the JavaScript file to start the application with.
If you are going to trace CoffeeScript, specify the path to the generated JavaScript file. The file can be generated externally or through compilation using File Watchers. For more information, refer to Debugging CoffeeScript.
The trace server port is filled in automatically. To avoid port conflicts, it is recommended that you accept the suggested value and keep the Automatically configure system proxy checkbox selected. As a result, the specified port number is automatically set for the system proxy server.
Alternatively, configure your system proxy port manually.
Go to Use a proxy server. In the Port field, type the trace server port number.
and turn onLearn more from the Microsoft official website.
Go to Advanced, switch to the Proxies tab, clear the Automatic Proxy Configuration, and type the URL address of your Proxy configuration file. Make sure, the port in the URL is the same as the trace server port from your run/debug configuration.
, clickLearn more from the Apple official website.
Specify the configuration file with the configuration settings to apply to the tracing session.
A configuration file is a JavaScript file with the extension .js or .conf.js that contains valid JavaScript code that meets the Spy-js configuration requirements. If PyCharm detects files with the extension .conf.js in the project, these files are displayed in the list.
Type the path to the configuration file manually or click Browse and choose the location in the dialog that opens. Once specified, a configuration file is added to the list so you can get if next time from the list instead of specifying the path.
Optionally:
Type the Node Parameters that customize the start of Node.js.
For example, to enable tracing ECMAScript 6 scripts, specify
--harmony
as a Node parameter. Note that Node.js must be version 0.11.13 or later.Choose working directory of the application.
By default, the field shows the project root folder.
Specify the Node.js-specific arguments to be passed to the application on start through the process.argv array.
Specify the environment variables for the Node.js executable file, if applicable. For more information, refer to Run/Debug Configuration: Spy-js for Node.js.
To start tracing a Node.js application
Choose the newly created configuration in the Select run/debug configuration list on the toolbar and click . The Spy-js Tool Window opens showing the captured events in the Trace Run tab.
Saving and loading tracing sessions
Spy-js stores the calls and properties of a tracing session in .json files that can be compressed into a zip archive. You can extract them at any time later to load the tracing session image into Spy-js. Note that a loaded image does not restore the session because no scripts are actually executed. All you can do is analyze the flow and properties of previously executed code.
To save an image of a tracing session
Click on the Events toolbar, and then choose Save trace from the list. PyCharm compresses all the affected .json files in a zip archive and opens the folder where the archive is saved.
To load an image of a previous tracing session
To activate Spy-js, start a tracing session of the same type as the session saved in the image, Spy-js or a Spy-js for Node.js respectively, refer to Initiating a Spy-js Tracing Session above.
Click the button on the Events toolbar and choose Load Trace from the list.
In the dialog that opens, choose the location of the zip archive with the image of the desired session. Spy-js stops the running and shows the loaded trace in a new tab named Loaded <loaded session>.
Configuring the event capturing policy
By default, Spy-js captures all events on all opened Web pages, excluding https secure web sites, unless you specify their URL addresses explicitly in the run configuration. All the captured events are shown on the Events pane of the Spy-js tool window. You can suppress capturing some types of events by applying user-defined event filters.
You can define new custom filters or add event patterns to existing filters on the fly.
To view the available configured filters
Click on the toolbar. The currently applied filter is marked with a tick. By default the Capture All predefined filter is applied.
To stop capturing events without stopping the application
Click the Capture Events button on the toolbar and choose Mute All from the context menu. The application is still running but the Events pane shows the last captured event. This is helpful if you want to analyze a script and therefore need it to be displayed in the Events pane but not removed as new events are captured.
To define a new event filter
Click the Capture Events button on the toolbar, and then choose Edit Capture Exclusions from the list.
In the Spy-js Capture Exclusions Dialog that opens, click Add on the left-hand pane.
In the right-hand pane, specify the filter name in the Exclusion name field and configure a list of exclusion rules.
To add a rule, click , the Add Condition to Exclusion dialog opens. Type a pattern in the Value/pattern field, in the Condition type list specify whether the pattern should be applied to event types or script names. Note that glob pattern matching is used. When you click OK, PyCharm brings you to the Spy-js Capture Exclusions Dialog.
To edit a rule, select it in the list, click , and update the rule in the dialog that opens. To remove a rule, select it in the list and click .
To choose a filter to apply
Click and select the checkbox next to the required filter in the list. If no filters are configured or none of the available filters fits the task, create a new filter as described above.
While navigating through the tree of already captured events in the Events pane, you may come across some events or scripts that you definitely do not want to trace. You can create a filter as described above but in this case you will have to leave the pane. With PyCharm, you can create an exclusion rule based on any event or script, as soon as you have detected such event or script, right from the Events pane.
To create an exclusion rule on the fly
Select the event to exclude and choose Mute <event name> event or Mute <script name> file. If a user-defined filter is currently applied, the new rule is added to it silently. If Capture All is currently active, the Spy-js Capture Exclusions Dialog opens, where you can create a new filter based on the selected event or script or choose an existing filter and add the new rule to it.
Timestamp labels help you to analyze your code execution within a specific period of time. For example, you can set two timestamp labels and view which events were captured between them. Or on the contrary, you can locate the events that were not captured within a certain period of time although you expected them to be and thus detect performance problems.
To set a timestamp label
Choose Add Label from the context menu in the Events pane. A label Labelled at <timestamp> is added under the document node.
Navigating between the panes and the editor
The Event Stack pane is synchronized with the Events pane and with the editor.
To view the call stack of a script or an event
Click the event or the script in the Events pane. Its call stack is shown in the Event Stack pane.
Optionally: to open the corresponding trace file in the editor automatically, press the Autoscroll to Trace toggle button on the toolbar.
To open the trace file of an event or a script in the editor
A trace file is a write-protected prettified version of a script and is named <script name>.js.trace.
In the Event Stack pane, click the script or event twice or choose Jump to Trace on its context menu.
Activate automatic navigation (click Autoscroll to Trace) and click the required event or script in the Events pane.
To synchronize the Events pane directly with the editor
Press the Autoscroll to Trace toggle button on the toolbar.
After that, on clicking a node in the Events pane, PyCharm shows its call stack in the Event Stack pane aqnd opens the corresponding trace file in the editor. Also, when you scroll through the Event Stack PyCharm automatically opens the corresponding files in the editor and highlights the called functions.
To navigate from a function to its call
In the Event Stack pane, select the required item in the call stack and choose Jump to Caller from the context menu of the selection.
Navigating through ECMAScript 6, TypeScript, or CoffeeScript
Spy-js supports source maps, which means that you can now jump from the Event Stack pane right to the original source code in ECMAScript 6, TypeScript or CoffeeScript and observe what code fragments were executed.
Spy-js also generates mapped trace files. These are EcmaScript 6, TypeScript, or CoffeeScript trace files with the extensions .ts.trace, .coffee.trace, or .js.trace. The fragments of code in these files are highlighted as if they were really executed.
Alternatively, you can navigate to the executed JavaScript code by choosing Jump to Trace.
To configure processing of source maps
Configure the way source maps are treated by clicking on the toolbar of the Events stack and choosing the following options from the context menu:
Choose Enable Source Map Look-up to enable navigation to the ECMAScript 6, TypeScript or CoffeeScript source code using the source maps generated during compilation.
Choose Enable source map generation, to generate source maps for everything to map the instrumented code. Choose this option if you are going to debug the original code in Chrome Dev Tools or FireFox FireBug development tools.
Choose Always open source mapped trace if available, to have Spy-js try to open the mapped trace file when you invoke navigation from an event to its caller.
To navigate from a function call to its source code
In the Event Stack pane, select the function and choose one of the following options from the context menu of the selection:
To navigate to the ECMAScript 6, TypeScript or CoffeeScript source code, choose Jump to Source from the context menu of the selection.
To navigate to the JavaScript trace file, choose Jump to Trace.
To navigate to the mapped trace file (ECMAScript 6, TypeScript or CoffeeScript), choose Jump to Mapped Trace.
To navigate from a function to its call
Select the function in the Event Stack and choose Jump to Caller.
If the Always open source mapped trace if available option is selected, the corresponding mapped trace file opens.
If the Always open source mapped trace if available option is not selected, the JavaScript trace file opens.
Advanced trace navigation
With advanced trace navigation, you can move through the whole stack based on calls and locate the functions that have not been called, that is, locate the fragments of code that have not been executed and analyze the reason for them to be skipped.
The following six actions are available: move to the next/previous call of the next/current/previous function in a trace file. The full list of actions is available from the context menu in the Event Stack pane. Moving to the next and previous calls of the selected function, to the previous call of the previous function, and to the next call of the next function are also available from the navigation toolbar of the Event Stack pane.
When you choose one of these actions, the caret jumps to the call in the stack. If the Autoscroll to Trace toggle button is pressed, the corresponding trace file opens automatically with the caret placed at the call.
Advanced trace search
Advanced trace search lets you navigate between the calls of a function within the whole trace (across all the traced events). This means that if you are tracing 5 pages in the browser and the Events pane, accordingly, shows 5 document nodes, PyCharm searches for the calls of the selected function under all these nodes and displays the number of found calls of the function in the Status bar.
The search results are reset and the search toolbar is hidden when you invoke another advanced search or navigation.
Also keep in mind that the number of call occurrences is calculated when you choose the Search this function calls across all events option. As you analyze the detected calls, the time passes, new events are captured, and the first detected call can happen to be already removed from the stack which means that it is no longer available for navigation.
To search for the calls of a function in all document nodes
Select the function in the Event Stack pane and choose Search this function calls across all events from the context menu of the selection.
The number of found calls is displayed in the Status bar, and the toolbar shows four previously hidden navigation chevron buttons.
To navigate within the found calls
use the chevron buttons:
To jump to the first detected call, click .
To jump to the last detected call, click
To jump to the next detected call, click The Status bar shows a message: Occurrence <number> of <total number of detected calls>
To jump to the previous detected call, click .
Expanding the basic completion list with runtime data (Spy-js autocompletion)
The term Spy-js autocompletion denotes expanding the basic completion list with suggestions retrieved from the runtime data. The Spy-js autocompletion functionality is available from source files for the code that has already been executed (highlighted green in the corresponding trace file).
When you place the caret at a symbol in the source file and press Ctrl+Space, Spy-js retrieves data from the browser or from the running Node.js application and merges it with the basic completion list according to the following rules:
If an object both is present on the basic completion list and is retrieved from the runtime, the variant that provides more information about parameters, attributes, their type, etc. remains on the list.
To activate Spy-js autocompletion
Click the button on the Events toolbar, and then choose Enable Spy-js autocomplete and magnifier from the list.
Evaluating expressions without running a debugging session (Spy-js magnification)
The term Spy-js magnification denotes evaluating expressions without actually running a debugging session. When you click an expression or place the caret at it and press Ctrl+Alt+F8, a tooltip is displayed below the expression showing the expression value. If Spy-js retrieves several values, click icon in the tooltip to expand the list of values.
The magnification functionality is available from source files for both executed and not yet executed code.
By default, the functionality is turned off.
To activate Spy-js magnification
Click the button on the Events toolbar, and then choose Enable Spy-js autocomplete and magnifier from the list.
Viewing dependency diagrams
With Spy-js, you can build and examine runtime application/event diagrams for client-side and Node.js applications.
Generate a diagram:
To build a diagram with the dependencies within the entire application, select the document node and choose Show application dependency diagram from the context menu of the selection.
To build a diagram with the dependencies of a single event, select the required event in the Events pane and choose Show event dependency diagram.
Analyze the diagram:
The diagram is opened in a separate editor tab. The nodes in the diagram represent your project files, while the edges represent the fact that there’s one or more functions in the source file that invoke functions in the target file.
To examine the details of a node or an edge, select the node or the edge and view its Details tree in a dedicated pane in the upper right-hand corner of the editor. The pane displays the connecting function combinations, along with event(s) the calls are made within and the number of calls made.