com.smartgwt.client.docs

## Interface Debugging

-     public interface Debugging

  ### Debugging

  #### Built-in Diagnostics

  The Smart GWT Developer Console is a suite of development tools implemented in Smart GWT itself. The Console runs in its own browser window, parallel to your running application, so it is always available in every browser, and in every deployment environment.

  The Developer Console can be opened by calling `isc.showConsole()` on any page in which Smart GWT has been loaded. You can create a bookmark in your browser to quickly show the Console on any Smart GWT application, without any changes to the application code:

  1. Create a new bookmark in your browser.
  2. Enter url "javascript:isc.showConsole()".
  3. Label the bookmark as "Show Console".
  4. Consider adding this to the Bookmarks Toolbar. This allows one-click access to the Console from any Smart GWT application.

  Note: For most browsers you can evaluate javascript directly from the browser URL bar by entering `javascript:string to evaluate` directly in the URL bar, so setting up a bookmark is not strictly necessary. For Firefox 6 and above, this feature has been disallowed, but the bookmark approach will still work. Alternatively developers could use Firefox Scratchpad to launch the console.

  Basic information on the features of the Developer Console can be found in the QuickStart Guide. For information about the "RPC" tab of the Developer Console and the request profiling information it can provide, see `the Developer Console RPC tab`. The remainder of this topic focuses on use of the log system and related debugging facilities.

  The Developer Console contains a "Results" pane that displays a list of diagnostic messages logged by the Smart GWT framework. The "Logging Preferences" menu lets you enable and disable Smart GWT's built-in diagnostics in several categories. Because important diagnostic messages may be logged at any time, you should have the Developer Console open whenever you are working with Smart GWT (and you should bookmark the "javascript:" expression above to make this easier).

  Log messages are of the format:

  timestamp:priority:category:message

  For example, the following log message:

            11:59:25:806:INFO:Page:Page loading complete.

  Occurred at 11:59:25 local time and 806 milliseconds. It's priority was `INFO`, it occurred in the category Page, and the message is "Page loading complete.".

  Each logging category has a priority associated with it. If a message's priority is lower than the current priority for the category it is logged in, the message will be suppressed (will not appear in the "Results" pane).

  It is critical to be familiar with the diagnostic categories built-in to Smart GWT - you will use them in most debugging sessions. Open the Logging Preferences menu and select "More.." to see a list of diagnostic log categories. Hover over each category name to see a description of what kind of messages are logged in the category.

  #### Debugging JavaScript Errors

  Javascript errors will typically be reported in the Developer Console. Wherever possible a stack trace will be included which can help determine the cause of the error. In addition to this, recent versions of the Firefox browser (versions 6.0 and above) ship with some useful development tools including the Error Console for reporting errors. We also recommend Console2 and Firebug for debugging in Firefox.

  In Internet Explorer, when JS errors occur, Smart GWT is able to report full stack traces in the Developer Console. This can be invaluable when your code triggers a JS error in the Smart GWT libraries themselves, or when it is unclear how your code is being called. Stack traces from Internet Explorer should always be included in issue reports sent to Isomorphic Software, if at all possible.

  #### Inspecting application state

  The "Evaluate JS Expression" area of the Results Pane in the Developer Console can be used to inspect the current state of a Smart GWT application. Any Smart GWT or browser built-in API can be called from the "Evaluate JS Expression" area, and the results will be intelligently summarized (via Log.echo()). For example, simply typing a component's ID and pressing the "Eval JS" button will give you a dump of it's current property values.

  Many, many Smart GWT APIs can be usefully called while troubleshooting, eg, `data` is a `ResultSet` when a grid is DataBound and `ResultSet.get()` can be called to inspect the current values on records. In addition, new application code can be tried out, for example, you might repeatedly instantiate a new component, trying variants on the properties you could give it.

  Inspecting transient application state with logs

  Transient state, such as the values of local variables in a method that is crashing, can be sent to the Developer Console via using the Log class. For example, to dump the value of the local variable "request":

            isc.logWarn("request is: " + isc.echo(request));

  It's a good idea to dump the values of local variables in any method that is crashing or behaving unexpectedly.

  Note the use of `logWarn()` above: in typical debugging sessions, it's best to simply use `logWarn` method to output diagnostics to ensure your message will not be suppressed by log priority settings.

  NOTE: never use the native `alert()` method to output diagnostics. Among other issues, `alert()` can affect timing, masking or altering the behavior you were trying to debug. Smart GWT's logging system doesn't suffer from these problems and provides much more control.

  #### Issue Reports

  If you believe you've discovered a bug in Smart GWT or you are having trouble using Smart GWT APIs, you can report it at http://forums.smartclient.com/, or, if you have Enterprise Support, at the Customer Support Extranet.

  How quickly your issue is resolved is entirely up to you. If you follow the steps below and submit an appropriate issue report, you will generally receive a rapid solution from Isomorphic Support, regardless of what support level you have, because Isomorphic aggressively corrects bugs and legitimate usage issues. If you skip steps you are likely to be directed back to this document and asked to submit a more complete issue report.

  Before reporting an issue, ensure that you:

  - Have read the 'QuickStart Guide' cover to cover. Later chapters cover more advanced topics and provide links to further examples and reference.
  - Have searched the ${isc.DocUtils.linkForDocNode('FeatureExplorer', 'Feature Explorer')} for examples that show what you are trying to do
  - Have searched this reference, trying multiple searches using different, common and related terms for what you are trying to do (eg for search, try "search", "filter", "criteria", "find", "match", etc)
  - Have searched the public forums
  Always include:
  - A description of what you are trying to accomplish from a user's perspective. The best answers often point out a simpler approach.
  - The browser(s), operating system(s) and Smart GWT version(s) you experience the error on (Smart GWT version is available in the lower-left handle corner of the Developer Console)
  Then, include either a standalone test case (see below), or:
  - For JS errors, Stack traces from Firebug (for Firefox) or the Developer Console (for IE), as covered under "Debugging JavaScript Errors" above
  - Results of calling `echo()` on local variables or other application state you think is relevant (see "Inspecting Application State" above)
  - What server platform and `databinding approach` you are using, if applicable
  - contents of the Smart GWT Developer Console "Log messages" area, with appropriate diagnostic categories set the DEBUG or INFO level (see "Built-in Diagnostics" above)
  - sample code and sample data
  Preparing a standalone test case

  A standalone test case is one of:

  1. a chunk of JavaScript code that can be executed from the "Eval JS" area of the Developer Console on some specified page within the unmodified Smart GWT SDK, demonstrating your issue
  2. an .html or .jsp file that can be dropped at a specified location into an unmodified Smart GWT SDK and will run without changes, demonstrating your issue.
  3. a .zip file that includes a standalone .html/.jsp file as above, as well as dependencies required to make the test case runnable, such as XML datasets

  Submitting a standalone test case removes any ambiguity as to whether there is a bug in Smart GWT or a bug in your code, and eliminates the possibility of Isomorphic Support responding with a "works for me" result due to incomplete information. Issues with verified test cases are routed directly to the engineer that authored the relevant Smart GWT subsystem, often as the new highest priority task. In addition, the process of preparing a test case very often allows you to solve the issue yourself.

  There are two approaches to test case preparation:

  1. Add code to an existing Smart GWT example until you can reproduce the problem
  2. Remove code from your application until it minimally shows the problem and runs standalone

  For approach #1, find the nearest match to your use case in the ${isc.DocUtils.linkForDocNode('FeatureExplorer')} examples or in the other examples accessible from the Examples folder of the SDK, then try to minimally modify that example to demonstrate your issue. Feature Explorer examples are a particularly good starting point because you can simply copy the code from the Feature Explorer to the Eval JS area of the Developer Console and begin changing it, and if successful this yields a type #1 test case, the easiest for you to submit and most efficient for Isomorphic to work with.

  For approach #2,

  1. If a server is involved in initial page generation (eg a .jsp file), in most cases you can eliminate many server dependencies and create an easily modifiable starting point by using the browser's "View Source" feature to save a copy of the generated HTML output as an .html file in the same directory as the .jsp file that generated it. Such a file will generally continue to function (all relative paths are still correct), and can be modified freely without the need to later revert changes to a .jsp.
  2. Eliminate any code that isn't involved in the interaction. Keep running the test case as you eliminate code to ensure you are still seeing the issue (you may solve it this way, or find key preconditions that you can report to Isomorphic)
  3. For any issue that isn't cosmetic, revert to a default Smart GWT skin
  4. For any necessary RPC/DataSource interactions, spoof the interaction with one of these approaches:
     - switch any DataSources to one of the sample DataSources from the SDK (eg "supplyItem") if your issue can still be reproduced in this case.
     - create a small sample dataset in JavaScript directly in the .html file, and use a `clientOnly DataSource` with that dataset.
     - capture server responses verbatim by setting the RPCManager log category to DEBUG, save the responses as flat files, and set `dataURL` to point at them.
     - for RPCs, instead of calling the RPCManager, directly call your own callback function, passing a spoofed RPCResponse that includes just the fields your code depends upon
  5. Finally, move your .html file into the stock Smart GWT SDK along with any remaining dependencies and verify the problem can still be reproduced
  Having prepared the test case, combine it with the other required issue report information covered above, and submit it to the forums, or, if you have Enterprise Support, at the Customer Support Extranet.

  #### Adding your own diagnostic categories

  Calling `logWarn()` is fine for a log statement you plan to delete at the end of the debugging session. However, many log statements have lasting value if you could enable or disable them only when you need the relevant diagnostics, like Smart GWT's built-in diagnostic categories. To do this, pick a priority level less than `WARN` (`INFO` or `DEBUG`), and call the corresponding method on the Log class (`logInfo()` or `logDebug()`), passing the category name as a second parameter. For example:

          isc.Log.logInfo("first record is: " +
                          isc.Log.echo(myGrid.data.get(0)),
                         "myGridLoading");

  This message will no longer appear in the Results Pane by default, because its priority (`INFO`) is less than the default of `WARN`. To see this message, open the Logging Preferences menu and pick "More..", then click the "Add" button, enter "myGridLoading" as the category name and set the priority to `INFO`. The message will now appear next time it is logged.

  Now you have a custom log category that you and other developers can use to debug your application, subsystem by subsystem. These diagnostics will be available to you both in development and production environments.

  As with Smart GWT's built-in diagnostics, you may choose to log certain messages in your custom category at the `DEBUG` level and a lesser number of messages at the `INFO` level, to create different depths of diagnostic output.

  #### Logging refinements

  The core log methods (`logDebug()`, `logInfo()`, `logWarn()`) and the "echo" facilities (`echo()` and `echoAll()`) are available on every Smart GWT component and Class. Hence, in many cases, the special JavaScript value "this" will refer to an object that supports `logWarn()` et al. For example:

            Canvas.create({
               ID:"canvasExample",
               contents:"Hello World!",
               click:"this.logWarn('the Canvas is: ' + this.echo(this))"
            });

  The special value "this" is not always set to a Smart GWT component, for example, in some kinds of callbacks (eg `fetchData()`). When in doubt, use these methods via the Log class as `isc.Log.logWarn()`.

  Logging performance

  Because the log message is actually formed before the call to the log system, logs that are suppressed can still carry a performance penalty. This is particularly true of logs that output a lot of data or occur frequently. To avoid this penalty, you can check in advance whether a message will be suppressed using isc.Log.logIsDebugEnabled() and isc.Log.logIsInfoEnabled(). For example:

          if (isc.Log.logIsInfoEnabled("myGridLoading")) {
             isc.Log.logInfo("first record is: " +
                             isc.Log.echo(myGrid.data.get(0)),
                             "myGridLoading");
          }

  Generally, it is only important to do this for logs that will occur multiple times during a given user interaction (eg a mousedown or keypress) and/or that call `echo()` on objects with many properties.