When Good Code Goes Bad: Tools and Techniques for Troubleshooting Plone


Published on

Using real issues encountered in the wild, this session will help beginning integrators gain confidence in knowing what to do when Plone fails to behave as expected. Learn how to solve common problems like "My changes aren't taking effect" and "My Zope instance won't start," as well as how to use pdb to investigate more complex Python errors.

This talk is targeted at integrators who have some experience with Plone, but who are not confident in troubleshooting errors and other unexpected behavior. Knowledge of Python is not required, though at least a cursory familiarity with some programming language will make the talk more digestible.

Published in: Technology
1 Comment
  • Its really helpful to me and for a every novice to plone. Thanks a ton. It saved my time. And my kind request is come up with much more presentation regarding customizing plone default look and feel. And how to integrate paypal with plone site.
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide
  • When Good Code Goes Bad: Tools and Techniques for Troubleshooting Plone

    1. When Good Code Goes Bad: Tools and Techniques for Troubleshooting Plone Plone Conference 2008 David Glick Web Developer ONE/Northwest
    2. What we're going to cover <ul><li>1. Preparation for debugging </li></ul><ul><li>2. Debugging tools </li></ul><ul><li>3. 2 case studies </li></ul><ul><li>4. Tips & tricks </li></ul>
    5. Newbie programmer's reaction: Absolute terror
    6. Experienced programmer's reaction: Absolute terror
    7. Maybe it's a little bug...
    8. ...but who knows what's in there, really!
    9. What could be wrong? <ul><li>Trivial typo </li></ul><ul><li>Logic error </li></ul><ul><li>Failure to consider certain input values </li></ul><ul><li>Faulty assumptions about the state of the system </li></ul><ul><li>Deep voodoo </li></ul>
    10. Mental preparation
    11. Remember: You are in control.
    12. Remember: You are not alone.
    13. Use the source, Luke.
    14. Getting ready...
    15. Don't use debugging tools in production. <ul><li>Security </li></ul><ul><li>Performance </li></ul>
    16. Run zope in foreground mode. <ul><li>Buildout: </li></ul><ul><li>$ bin/instance fg </li></ul><ul><li>Pre-buildout: </li></ul><ul><li>$ zopectl fg </li></ul>
    17. Turn on verbose security. <ul><li>Buildout: </li></ul><ul><li>in buildout.cfg, [instance] section: </li></ul><ul><li>verbose-security on </li></ul><ul><li>Pre-buildout: </li></ul><ul><li>in zope.conf: </li></ul><ul><li>verbose-security on </li></ul><ul><li>security-policy-implementation python </li></ul>
    18. Stop ignoring errors in /error_log
    19. Debugging tools
    20. 1. What is that thing?
    21. <ul><li>Firebug (Firefox) </li></ul><ul><li>http://tinyurl.com/2z4tvg </li></ul><ul><li>IE Web Developer Toolbar (IE) http://tinyurl.com/iedevtoolbar </li></ul><ul><li>WebKit (Safari) http://webkit.org </li></ul><ul><li>Google Chrome inspector </li></ul>Investigating HTML, CSS, and Javascript >
    22. Investigating Plone viewlets and portlets <ul><li>plone.app.gloworm http://tinyurl.com/gloworm </li></ul>
    23. Investigating the current page context <ul><li>Products.Clouseau http://tinyurl.com/clouseau </li></ul>
    24. 2. What code controls this?
    25. Seek and ye shall find! <ul><li>Grep </li></ul><ul><li>Multi-file search and replace feature in editor of choice </li></ul><ul><li>Code indexers (etags, glimpse) </li></ul>
    26. Where is the code? <ul><li>From a filesystem page template: </li></ul><ul><li><tal:block tal:replace=”python:obj.__class__”/> </li></ul><ul><li>(gives you the dotted path of module + class of obj) </li></ul><ul><li>From any page template: </li></ul><ul><li><tal:block tal:replace=”nocall:obj”/> </li></ul><ul><li>(gives you the class name of obj) </li></ul>
    27. collective.recipe.omelette <ul><li>Before : </li></ul><ul><li>After: </li></ul>http://tinyurl.com/collective-omelette
    28. 3. What's that code doing?
    29. Logging <ul><li>context.plone_log(my_var) </li></ul><ul><li>Output will show up on console </li></ul><ul><li>Useful for when some code is being run repeatedly and you want to make sure it's operating on the correct values </li></ul>
    30. pdb: the Python debugger
    31. pdb: the Python debugger <ul><li>Trigger with: </li></ul><ul><li>import pdb; pdb.set_trace() </li></ul><ul><li>Don't forget to remove the set_trace! </li></ul>
    32. 4. What's Zope doing right now? <ul><li>DebugInfo page (built in): /ControlPanel/DebugInfo/manage_main in ZMI </li></ul><ul><li>DeadlockDebugger product http://tinyurl.com/deadlockdebugger </li></ul>
    33. 5. Why is this so slow ? <ul><li>YSlow – frontend performance </li></ul><ul><li>http://developer.yahoo.com/yslow/ </li></ul><ul><li>PTProfiler – page templates </li></ul><ul><li>http://plone.org/products/ptprofiler </li></ul><ul><li>ZopeProfiler – Python calls </li></ul><ul><li>http://pypi.python.org/pypi/Products.ZopeProfiler </li></ul>
    34. What does it look like in real life? <ul><li>Case #1: </li></ul><ul><li>plone_newbie4022's Quick Installer problem </li></ul><ul><li>(from #plone, 2008-09-08) </li></ul>
    35. Reading a traceback module Line # method More recent <ul><li>Snapshot of what code is executing </li></ul><ul><li>Doesn't include the values </li></ul>
    36. Reading a traceback (cont'd) For page template expressions Template file location The actual TAL expression that was called Location of expression within the template The actual Error message! Bonus (but irrelevant) error The Error happened here!
    37. Common Python exceptions <ul><li>AttributeError </li></ul><ul><ul><li>e.g. obj.nonexistent_attribute </li></ul></ul><ul><li>ImportError </li></ul><ul><ul><li>e.g. import nonexistent_module </li></ul></ul><ul><li>IndexError </li></ul><ul><ul><li>e.g. my_list[42] , if my_list doesn't have >=43 elements </li></ul></ul>
    38. Common Python exceptions <ul><li>KeyError </li></ul><ul><ul><li>e.g. my_dict['nonexistent_key'] </li></ul></ul><ul><li>TypeError </li></ul><ul><ul><li>e.g. foo = ('tuple',) + 'string' </li></ul></ul><ul><li>ValueError </li></ul><ul><ul><li>e.g. int('string') </li></ul></ul>
    39. Common Zope exceptions <ul><li>Unauthorized </li></ul><ul><li>NotFound </li></ul><ul><li>Redirect </li></ul><ul><li>TraversalError </li></ul><ul><li>ComponentLookupError – failed zope 3 lookup </li></ul><ul><li>ConflictError – ZODB conflict </li></ul>
    40. Lessons from Case #1
    41. <ul><li>The problem is sometimes (usually?) not where you think the problem is. </li></ul>
    42. <ul><li>Think carefully about both: </li></ul><ul><ul><li>What the code is doing </li></ul></ul><ul><ul><li>What the state is of the objects in your ZODB </li></ul></ul>
    43. <ul><li>Often you don't have to change any code to fix a bug, once you understand what is going on. </li></ul>
    44. What does it look like in real life? <ul><li>Case #2: </li></ul><ul><li>some (only somewhat) contrived </li></ul><ul><li>catalog trouble </li></ul>
    45. plone.reload <ul><li>Reload Python code without restarting Zope. </li></ul><ul><li>Just go to /@@reload. </li></ul>
    46. pdb commands <ul><li>l / list: print the code. l 42 == list line #42 </li></ul><ul><li>w / where: print a traceback </li></ul><ul><li>n / next: run the next command </li></ul><ul><li>s / step: enter a method that is being called </li></ul><ul><li>r / return: execute until the current method completes </li></ul><ul><li>c / continue: continue execution indefinitely (end pdb session) </li></ul>
    47. advanced pdb commands <ul><li>b / breakpoint: b 42 == set a breakpoint on line 42 </li></ul><ul><li>cl / clear: cl 1 == remove breakpoint #1 </li></ul><ul><li>j / jump: j 42 == jump to line 42 </li></ul><ul><li>u / up: move up in the call stack </li></ul><ul><li>d / down: move down in the call stack </li></ul><ul><li>Full pdb docs: http://www.python.org/doc/2.5.2/lib/module-pdb.html </li></ul>
    48. pdb idioms <ul><li>pp obj – pretty-print an object </li></ul><ul><li>dir(obj) – list an object's attributes and methods </li></ul><ul><li>obj.__dict__ -- list an object's data attributes </li></ul><ul><li>obj.__doc__ -- print an object's docstring </li></ul><ul><li>args – list the arguments passed to the current method </li></ul><ul><li>retval – print the value that will be returned from the current method </li></ul><ul><li>!expr – force expr to be treated as a Python expression rather than a pdb command </li></ul>
    49. Lessons from Case #2
    50. <ul><li>If you don't have a traceback, finding the source of misbehavior can be hard . Be persistent.* </li></ul><ul><li>* Bad Zope pun not intended. </li></ul>
    51. <ul><li>Try the most obvious things first. (Assume there's a bug in your own code, rather than in Zope/Plone.) </li></ul>
    52. Tips and Tricks
    53. PDBDebugMode product <ul><li>Automatically get a pdb whenever there is a python exception </li></ul><ul><li>Invoke a pdb on any context via /@@pdb view </li></ul><ul><li>Invoke a pdb on anything via /path/to/anything?pdb_runcall=1 </li></ul>
    54. Debugging python scripts <ul><li>Use the zdb product http://www.simplistix.co.uk/software/zope/zdb </li></ul><ul><ul><li>from Products.zdb import set_trace; set_trace() </li></ul></ul><ul><ul><li>Ensures that you can (l)ist the code of the Python script </li></ul></ul><ul><ul><li>Doesn't work for form controller Python scripts (.cpy) though </li></ul></ul><ul><li>When stepping into calls in restricted python, you will first enter guarded_getattr, which you can (r)eturn out of and then the (n)ext call will be the one you want </li></ul>
    55. Tab key auto-completion in pdb <ul><li>Add the following to ~/.pdbrc: </li></ul><ul><li>import rlcompleter </li></ul><ul><li>pdb.Pdb.complete = rlcompleter.Completer(locals()).complete </li></ul>
    56. Why aren't my changes coming alive? <ul><li>template, image & stylesheet customizations: </li></ul><ul><ul><li>put CSS, Javascript, KSS registries in debug mode, or at least re-save them </li></ul></ul><ul><ul><li>make sure you don't have something in portal_skins/custom or portal_view_customizations that's overriding your filesystem item </li></ul></ul><ul><ul><li>flush browser cache </li></ul></ul>
    57. Why aren't my changes coming alive? <ul><li>changes to python code or ZCML: </li></ul><ul><ul><li>restart Zope, or use plone.reload </li></ul></ul>
    58. Why aren't my changes coming alive? <ul><li>changes to GenericSetup profiles: </li></ul><ul><ul><li>re-run profile or reinstall product (don't need to restart zope) </li></ul></ul><ul><li>installing a new product: </li></ul><ul><ul><li>if not in the Products namespace, did you add a ZCML slug? </li></ul></ul>
    59. Debugging KSS <ul><li>Use the FireKiss add-on for Firebug: http://tinyurl.com/firekiss </li></ul><ul><li>Configure KSS debug log at /@@kss_devel_mode/ui </li></ul><ul><li>Be aware that KSS will time out if you try to put a pdb set_trace in your server-side KSS action code </li></ul>
    60. Common red herrings
    61. “Not authorized to access binding.” <ul><li>A deferred permission error from earlier in code execution. </li></ul><ul><li>See http://tinyurl.com/unauthorizedbinding </li></ul>
    62. Quick Installer swallows import errors <ul><li>(Fixed in Plone 3.1.2) </li></ul>
    63. AttributeError: getGroups <ul><li>Usually means you moved the site to a new Zope, whose acl_users needs to be converted to be PAS-enabled. </li></ul><ul><li>You can trigger that conversion by adding a brand new Plone site. </li></ul>
    64. “No traversable adapter found.” <ul><li>Usually a symptom of Five failing to load. </li></ul><ul><li>Start Zope in foreground mode and watch the console for the real traceback. </li></ul>
    66. Credits <ul><li>Cave openings, screenshots – David Glick </li></ul><ul><li>First computer bug – US Navy / public domain </li></ul><ul><li>Flickr users: </li></ul><ul><ul><li>rotten apples – alisonedunn – CC Attribution </li></ul></ul><ul><ul><li>gearing up for spelunking – jarvist – CC Attribution </li></ul></ul><ul><ul><li>pause button – Jobot Da Robot – CC Attribution Share Alike </li></ul></ul><ul><ul><li>“ debug yourself” – joshlewis – CC Attribution NC Share Alike </li></ul></ul><ul><ul><li>“ no fish” – waldopepper – CC Attribution NC </li></ul></ul><ul><li>These slides are licensed under the following license: Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License </li></ul>