1Catalyst::Manual::TutorUisaelr::C0o7n_tDreibbuugtCgeaidtnagPl(ey3rs)lt:D:oMcaunmueanlt:a:tTiuotnorial::07_Debugging(3)
2
3
4
6 Catalyst::Manual::Tutorial::07_Debugging - Catalyst Tutorial - Chapter
7 7: Debugging
8
10 This is Chapter 7 of 10 for the Catalyst tutorial.
11
12 Tutorial Overview
13
14 1. Introduction
15
16 2. Catalyst Basics
17
18 3. More Catalyst Basics
19
20 4. Basic CRUD
21
22 5. Authentication
23
24 6. Authorization
25
26 7. 07_Debugging
27
28 8. Testing
29
30 9. Advanced CRUD
31
32 10. Appendices
33
35 This chapter of the tutorial takes a brief look at the primary options
36 available for troubleshooting Catalyst applications.
37
38 Note that when it comes to debugging and troubleshooting, there are two
39 camps:
40
41 · Fans of "log" and "print" statements embedded in the code.
42
43 · Fans of interactive debuggers.
44
45 Catalyst is able to easily accommodate both styles of debugging.
46
48 Folks in the former group can use Catalyst's "$c->log" facility. (See
49 Catalyst::Log for more detail.) For example, if you add the following
50 code to a controller action method:
51
52 $c->log->info("Starting the foreach loop here");
53
54 $c->log->debug("Value of \$id is: ".$id);
55
56 Then the Catalyst development server will display your message along
57 with the other debug output. To accomplish the same thing in a TT
58 template view use:
59
60 [% c.log.debug("This is a test log message") %]
61
62 As with many other logging facilities, a method is defined for each of
63 the following "logging levels" (in increasing order of
64 severity/importance):
65
66 $c->log->debug
67 $c->log->info
68 $c->log->warn
69 $c->log->error
70 $c->log->fatal
71
72 You can also use Data::Dumper in both Catalyst code ("use Data::Dumper;
73 $c->log->debug("\$var is: ".Dumper($var));)") and TT templates ("[%
74 Dumper.dump(book) %]".
75
77 Members of the interactive-debugger fan club will also be at home with
78 Catalyst applications. One approach to this style of Perl debugging is
79 to embed breakpoints in your code. For example, open
80 "lib/MyApp/Controller/Books.pm" in your editor and add the
81 "DB::single=1" line as follows inside the "list" method (I like to
82 "left-justify" my debug statements so I don't forget to remove them,
83 but you can obviously indent them if you prefer):
84
85 sub list :Local {
86 # Retrieve the usual Perl OO '$self' for this object. $c is the Catalyst
87 # 'Context' that's used to 'glue together' the various components
88 # that make up the application
89 my ($self, $c) = @_;
90
91 $DB::single=1;
92
93 # Retrieve all of the book records as book model objects and store in the
94 # stash where they can be accessed by the TT template
95 $c->stash->{books} = [$c->model('DB::Book')->all];
96
97 # Set the TT template to use. You will almost always want to do this
98 # in your action methods.
99 $c->stash->{template} = 'books/list.tt2';
100 }
101
102 This causes the Perl Debugger to enter "single step mode" when this
103 command is encountered (it has no effect when Perl is run without the
104 "-d" flag).
105
106 NOTE: The "DB" here is the Perl Debugger, not the DB model.
107
108 If you haven't done it already, enable SQL logging as before:
109
110 $ export DBIC_TRACE=1
111
112 To now run the Catalyst development server under the Perl debugger,
113 simply prepend "perl -d" to the front of "script/myapp_server.pl":
114
115 $ perl -d script/myapp_server.pl
116
117 This will start the interactive debugger and produce output similar to:
118
119 $ perl -d script/myapp_server.pl
120
121 Loading DB routines from perl5db.pl version 1.3
122 Editor support available.
123
124 Enter h or `h h' for help, or `man perldebug' for more help.
125
126 main::(script/myapp_server.pl:16): my $debug = 0;
127
128 DB<1>
129
130 Press the "c" key and hit "Enter" to continue executing the Catalyst
131 development server under the debugger. Although execution speed will
132 be slightly slower than normal, you should soon see the usual Catalyst
133 startup debug information.
134
135 Now point your browser to <http://localhost:3000/books/list> and log
136 in. Once the breakpoint is encountered in the
137 "MyApp::Controller::list" method, the console session running the
138 development server will drop to the Perl debugger prompt:
139
140 MyApp::Controller::Books::list(/home/me/MyApp/script/../lib/MyApp/Controller/Books.pm:48):
141 48: $c->stash->{books} = [$c->model('DB::Book')->all];
142
143 DB<1>
144
145 You now have the full Perl debugger at your disposal. First use the
146 "next" feature by typing "n" to execute the "all" method on the Book
147 model ("n" jumps over method/subroutine calls; you can also use "s" to
148 "single-step" into methods/subroutines):
149
150 DB<1> n
151 SELECT me.id, me.title, me.rating, me.created, me.updated FROM book me:
152 MyApp::Controller::Books::list(/home/me/MyApp/script/../lib/MyApp/Controller/Books.pm:53):
153 53: $c->stash->{template} = 'books/list.tt2';
154
155 DB<1>
156
157 This takes you to the next line of code where the template name is set.
158 Notice that because we enabled "DBIC_TRACE=1" earlier, SQL debug output
159 also shows up in the development server debug information.
160
161 Next, list the methods available on our "Book" model:
162
163 DB<1> m $c->model('DB::Book')
164 ()
165 (0+
166 (bool
167 __result_class_accessor
168 __source_handle_accessor
169 _add_alias
170 __bool
171 _build_unique_query
172 _calculate_score
173 _collapse_cond
174 <lines removed for brevity>
175
176 DB<2>
177
178 We can also play with the model directly:
179
180 DB<2> x ($c->model('DB::Book')->all)[1]->title
181 SELECT me.id, me.title, me.rating, me.created, me.updated FROM book me:
182 0 'TCP/IP Illustrated, Volume 1'
183
184 This uses the Perl debugger "x" command to display the title of a book.
185
186 Next we inspect the "books" element of the Catalyst "stash" (the 4
187 argument to the "x" command limits the depth of the dump to 4 levels):
188
189 DB<3> x 4 $c->stash->{books}
190 0 ARRAY(0xa8f3b7c)
191 0 MyApp::Model::DB::Book=HASH(0xb8e702c)
192 '_column_data' => HASH(0xb8e5e2c)
193 'created' => '2009-05-08 10:19:46'
194 'id' => 1
195 'rating' => 5
196 'title' => 'CCSP SNRS Exam Certification Guide'
197 'updated' => '2009-05-08 10:19:46'
198 '_in_storage' => 1
199 <lines removed for brevity>
200
201 Then enter the "c" command to continue processing until the next
202 breakpoint is hit (or the application exits):
203
204 DB<4> c
205 SELECT author.id, author.first_name, author.last_name FROM ...
206
207 Finally, press "Ctrl+C" to break out of the development server.
208 Because we are running inside the Perl debugger, you will drop to the
209 debugger prompt.
210
211 ^CCatalyst::Engine::HTTP::run(/usr/local/share/perl/5.10.0/Catalyst/Engine/HTTP.pm:260):
212 260: while ( accept( Remote, $daemon ) ) {
213
214 DB<4>
215
216 Finally, press "q" to exit the debugger and return to your OS shell
217 prompt:
218
219 DB<4> q
220 $
221
222 For more information on using the Perl debugger, please see "perldebug"
223 and "perldebtut". For those daring souls out there, you can dive down
224 even deeper into the magical depths of this fine debugger by checking
225 out "perldebguts".
226
227 You can also type "h" or "h h" at the debugger prompt to view the
228 built-in help screens.
229
230 For an excellent book covering all aspects of the Perl debugger, we
231 highly recommend reading 'Pro Perl Debugging' by Richard Foley.
232
233 Oh yeah, before you forget, be sure to remove the "DB::single=1" line
234 you added above in "lib/MyApp/Controller/Books.pm".
235
237 Although the techniques discussed above work well for code you are
238 writing, what if you want to use print/log/warn messages or set
239 breakpoints in code that you have installed from CPAN (or in module
240 that ship with Perl)? One helpful approach is to place a copy of the
241 module inside the "lib" directory of your Catalyst project. When
242 Catalyst loads, it will load from inside your "lib" directory first,
243 only turning to the global modules if a local copy cannot be found.
244 You can then make modifications such as adding a "$DB::single=1" to the
245 local copy of the module without risking the copy in the original
246 location. This can also be a great way to "locally override" bugs in
247 modules while you wait for a fix on CPAN.
248
249 Matt Trout has suggested the following shortcut to create a local copy
250 of an installed module:
251
252 mkdir -p lib/Module; cp `perldoc -l Module::Name` lib/Module/
253
254 Note: If you are following along in Debian 5 or Ubuntu, you will need
255 to install the "perl-doc" package to use the "perldoc" command. Use
256 "sudo aptitude install perl-doc" to do that.
257
258 For example, you could make a copy of Catalyst::Plugin::Authentication
259 with the following command:
260
261 mkdir -p lib/Catalyst/Plugin; cp \
262 `perldoc -l Catalyst::Plugin::Authentication` lib/Catalyst/Plugin
263
264 You can then use the local copy inside your project to place logging
265 messages and/or breakpoints for further study of that module.
266
267 Note: Matt has also suggested the following tips for Perl debugging:
268
269 · Check the version of an installed module:
270
271 perl -M<mod_name> -e 'print "$<mod_name>::VERSION\n"'
272
273 For example:
274
275 $ perl -MCatalyst::Plugin::Authentication -e \
276 'print $Catalyst::Plugin::Authentication::VERSION;'
277 0.07
278
279 and if you are using bash aliases:
280
281 alias pmver="perl -le '\$m = shift; eval qq(require \$m) \
282 or die qq(module \"\$m\" is not installed\\n); \
283 print \$m->VERSION'"
284
285 · Check if a modules contains a given method:
286
287 perl -MModule::Name -e 'print Module::Name->can("method");'
288
289 For example:
290
291 $ perl -MCatalyst::Plugin::Authentication -e \
292 'print Catalyst::Plugin::Authentication->can("user");'
293 CODE(0x9c8db2c)
294
295 If the method exists, the Perl "can" method returns a coderef.
296 Otherwise, it returns undef and nothing will be printed.
297
299 If you run into issues during the rendering of your template, it might
300 be helpful to enable TT "DEBUG" options. You can do this in a Catalyst
301 environment by adding a "DEBUG" line to the "__PACKAGE__-"config>
302 declaration in "lib/MyApp/View/TT.pm":
303
304 __PACKAGE__->config({
305 TEMPLATE_EXTENSION => '.tt2',
306 DEBUG => 'undef',
307 });
308
309 There are a variety of options you can use, such as 'undef', 'all',
310 'service', 'context', 'parser' and 'provider'. See Template::Constants
311 for more information (remove the "DEBUG_" portion of the name shown in
312 the TT docs and convert to lower case for use inside Catalyst).
313
314 NOTE: Please be sure to disable TT debug options before continuing with
315 the tutorial (especially the 'undef' option -- leaving this enabled
316 will conflict with several of the conventions used by this tutorial to
317 leave some variables undefined on purpose).
318
319 Happy debugging.
320
322 Kennedy Clark, "hkclark@gmail.com"
323
324 Please report any errors, issues or suggestions to the author. The
325 most recent version of the Catalyst Tutorial can be found at
326 http://dev.catalyst.perl.org/repos/Catalyst/Catalyst-Manual/5.80/trunk/lib/Catalyst/Manual/Tutorial/
327 <http://dev.catalyst.perl.org/repos/Catalyst/Catalyst-
328 Manual/5.80/trunk/lib/Catalyst/Manual/Tutorial/>.
329
330 Copyright 2006-2008, Kennedy Clark, under Creative Commons License
331 (http://creativecommons.org/licenses/by-sa/3.0/us/
332 <http://creativecommons.org/licenses/by-sa/3.0/us/>).
333
334
335
336perl v5.12.0 20C1a0t-a0l2y-s1t7::Manual::Tutorial::07_Debugging(3)