One of the harder problems that developers have to deal with is characterizing issues that show up only in production, especially if exceptions aren’t being thrown.
In development, you’d just toss a `self halt` or two into the code and you’d be off to the races, but in production where multiple servers are involved, things can get a little more complicated. Often developers must resort to print statement debugging and sophisticated server log mining tools to characterize production issues.
Remote Breakpoints to the Rescue
Breakpoints have been available in GLASS, for a long time now. In 2008 I added remote breakpoints for Seaside2.8 and finally with the release of Seaside 220.127.116.11, remote breakpoints are available for Seaside 3.0.
With remote breakpoints, you can easily set/clear breakpoints in all of the gems that are serving Seaside and when a breakpoint is encountered a continuation is snapped off and added to the ObjectLog. At your leisure, you can debug the continuation from GemTools or inspect the continuation via the ObjectLog.
- Setup for Remote Breakpoints:
- Launch Seaside
- Testing, Testing…:
Before using remote breakpoints, you need to do a little prep depending upon which version of GemStone/S you are using.
If you want to use remote breakpoints with GemStone/S 2.x, you need only install a new StartSeaside30 Adaptor script or add the following section to your own script:
true "enable for remote breakpoints and profiling" ifTrue: [ GemToGemAnnouncement installStaticHandler. Exception installStaticException: [:ex :cat :num :args | BreakpointNotification signal. "needed to avoid infinite loop when resuming from a breakpoint" ex _incrementBreakpointsToIgnore. ] category: GemStoneError number: 6005 subtype: nil. System commitTransaction ifFalse: [ nil error: 'Could not commit for GemToGemSignaling' ]].
The script support for remote breakpoints is preinstalled in GemStone/S 3.0.1, however you must disable native code by setting GEM_NATIVE_CODE_ENABLED to FALSE in your gem conf files:
GEM_NATIVE_CODE_ENABLED = FALSE;
In 3.x there are actually three conf files to think about:
By default, GEM_NATIVE_CODE_ENABLED is set to FALSE, but in a production installation you should set GEM_NATIVE_CODE_ENABLED to TRUE to get the best performance and only set it to FALSE if you want to enable remote breakpoints.
- Start up a GemTools development image.
- Specify the adaptor and number of Seaside server gems to be used (note that the Seaside30 session workspace also has the necessary template expressions).
- Start the Seaside server gems.
Lets run through the process of using remote breakpoints:
- Set Remote Breakpoint
- Trigger Breakpoint with WARemoteDebuggingWalkbackErrorHandler
- Trigger Breakpoint with WAGemStoneProductionErrorHandler
- Debug Breakpoint in GemTools
- View Breakpoint in ObjectLog
- Clear Remote Breakpoints
For this example we’ll set a breakpoint in the WAExceptionFunctionalTest>>raiseWarning method.
- If you’ve just started your Seaside gems for this test, then you should force a transaction by selecting either the ‘Commit’ or ‘Abort’ menu item on the GemTools Transaction menu. The list of running Seaside gems is maintained in a persistent list and the action for starting the gems from GemTools doesn’t involve a transaction. If there is no commit or abort between the time you’ve started the Seaside gems and set the breakpoint, the breakpoint will not be set in the Seaside gems.
- In the GemTools development image, bring up a class editor on the WAExceptionFunctionalTest>>raiseWarning method, place the cursor at the beginning of the #notify selector and select the ‘set breakpoint’ menu item:
- Bring up a web browser on the WAFunctionalTest page:
- Ensure that you are using either the WARemoteDebuggingWalkbackErrorHandler or WAGemStoneProductionErrorHandler by selecting the correct class from the error handler drop down list (don’t forget to click on the ‘Set Handler’ button):
- Trigger the breakpoint by clicking on the ‘Raise warning’ link:
- The Seaside Walkback page will come up:
- Click on the ‘Remote Debug’ link to snap off a continuation add it to the ObjectLog:
- The remote debug page will come up, confirming that the breakpoint continuation has been added to the ObjectLog:
- Go back to theWAFunctionalTest page and select the WAGemStoneProductionErrorHandler this time:
- When you trigger the breakpoint clicking on the ‘Raise warning’ link, instead of a walkback window you get the production error message window for the Warning that is signaled as part of the functional test:
- This pages is what you’d expect without the breakpoint, but since you are using the WAGemStoneProductionErrorHandler, the breakpoint continuation is snapped off and silently added to the ObjectLog along with a continuation for the Warning exception. We can check that by looking at the Debug menu in GemTools:
- In GemTools use the Debug menu to select the breakpoint continuation:
- and bring up the debugger on the continuation:
You can inspect continuations in the ObjectLog from your web browser by using the WAObjectLog component.
- Register the component by following the instructions on the ObjectLog page in the wiki.
- Hit http://localhost:8383/tools/objectLog in your web browser to bring up the Object Log page:
- Scan the list and find the item labeled ‘continuation’ and click on the ‘2’ link:
- When you click on the ‘2’ link you are taken to an object inspector on the ObjectLogEntry itself. From there you can navigate to the objects stashed in the entry:
- To view a printString of the stack click on the ‘ GsProcess(oop=206376961, status=debug, priority=15, WARemoteDebuggingWalkbackErrorHandler >> open:’ link:
- This page doesn’t provide as much information as the debugger view, but sometimes a stack trace is enough:
- To clear the breakpoints, you can bring up the text menu and select ‘clear ALL breakpoints’ to clear all of the breakpoints that may be set or ‘clear method breakpoints’ to clear the breakpoints that are set in the selected method: