Commit | Line | Data |
d442cc9f |
1 | =head1 NAME |
2 | |
3533daff |
3 | Catalyst::Manual::Tutorial::Debugging - Catalyst Tutorial - Part 7: Debugging |
4 | |
d442cc9f |
5 | |
6 | =head1 OVERVIEW |
7 | |
3533daff |
8 | This is B<Part 7 of 10> for the Catalyst tutorial. |
d442cc9f |
9 | |
10 | L<Tutorial Overview|Catalyst::Manual::Tutorial> |
11 | |
12 | =over 4 |
13 | |
14 | =item 1 |
15 | |
16 | L<Introduction|Catalyst::Manual::Tutorial::Intro> |
17 | |
18 | =item 2 |
19 | |
20 | L<Catalyst Basics|Catalyst::Manual::Tutorial::CatalystBasics> |
21 | |
22 | =item 3 |
23 | |
3533daff |
24 | L<More Catalyst Basics|Catalyst::Manual::Tutorial::MoreCatalystBasics> |
d442cc9f |
25 | |
26 | =item 4 |
27 | |
3533daff |
28 | L<Basic CRUD|Catalyst::Manual::Tutorial::BasicCRUD> |
d442cc9f |
29 | |
30 | =item 5 |
31 | |
3533daff |
32 | L<Authentication|Catalyst::Manual::Tutorial::Authentication> |
d442cc9f |
33 | |
34 | =item 6 |
35 | |
3533daff |
36 | L<Authorization|Catalyst::Manual::Tutorial::Authorization> |
d442cc9f |
37 | |
38 | =item 7 |
39 | |
3533daff |
40 | B<Debugging> |
d442cc9f |
41 | |
42 | =item 8 |
43 | |
3533daff |
44 | L<Testing|Catalyst::Manual::Tutorial::Testing> |
d442cc9f |
45 | |
46 | =item 9 |
47 | |
3533daff |
48 | L<Advanced CRUD|Catalyst::Manual::Tutorial::AdvancedCRUD> |
49 | |
50 | =item 10 |
51 | |
d442cc9f |
52 | L<Appendices|Catalyst::Manual::Tutorial::Appendices> |
53 | |
54 | =back |
55 | |
56 | |
57 | =head1 DESCRIPTION |
58 | |
59 | This part of the tutorial takes a brief look at the primary options |
60 | available for troubleshooting Catalyst applications. |
61 | |
62 | Note that when it comes to debugging and troubleshooting, there are two |
63 | camps: |
64 | |
65 | =over 4 |
66 | |
67 | =item * |
68 | |
69 | Fans of C<log> and C<print> statements embedded in the code. |
70 | |
71 | =item * |
72 | |
73 | Fans of interactive debuggers. |
74 | |
75 | =back |
76 | |
77 | Catalyst is able to easily accommodate both styles of debugging. |
78 | |
79 | =head1 LOG STATEMENTS |
80 | |
81 | Folks in the former group can use Catalyst's C<$c-E<gt>log> facility. |
82 | (See L<Catalyst::Log> for more detail.) For example, if you add the |
83 | following code to a controller action method: |
84 | |
85 | $c->log->info("Starting the foreach loop here"); |
86 | |
cae937d8 |
87 | $c->log->debug("Value of \$id is: ".$id); |
d442cc9f |
88 | |
89 | Then the Catalyst development server will display your message along |
90 | with the other debug output. To accomplish the same thing in a TTSite |
91 | view use: |
92 | |
8a7c5151 |
93 | [% c.log.debug("This is a test log message") %] |
d442cc9f |
94 | |
95 | You can also use L<Data::Dumper|Data::Dumper> in both Catalyst code |
8c4a5110 |
96 | (C<use Data::Dumper; $c-E<gt>log-E<gt>debug("\$var is: ".Dumper($var));)>) |
d442cc9f |
97 | and TT templates (C<[% Dumper.dump(book) %]>. |
98 | |
99 | =head1 RUNNING CATALYST UNDER THE PERL DEBUGGER |
100 | |
101 | Members of the interactive-debugger fan club will also be at home with |
102 | Catalyst applications. One approach to this style of Perl debugging is |
103 | to embed breakpoints in your code. For example, open |
104 | C<lib/MyApp/Controller/Books.pm> in your editor and add the |
105 | C<DB::single=1> line as follows inside the C<list> method (I like to |
106 | "left-justify" my debug statements so I don't forget to remove them, but |
107 | you can obviously indent them if you prefer): |
108 | |
109 | sub list : Local { |
3533daff |
110 | # Retrieve the usual Perl OO '$self' for this object. $c is the Catalyst |
d442cc9f |
111 | # 'Context' that's used to 'glue together' the various components |
112 | # that make up the application |
113 | my ($self, $c) = @_; |
114 | |
115 | $DB::single=1; |
116 | |
117 | # Retrieve all of the book records as book model objects and store in the |
118 | # stash where they can be accessed by the TT template |
d0496197 |
119 | $c->stash->{books} = [$c->model('DB::Books')->all]; |
d442cc9f |
120 | |
121 | # Set the TT template to use. You will almost always want to do this |
122 | # in your action methods. |
123 | $c->stash->{template} = 'books/list.tt2'; |
124 | } |
125 | |
126 | This causes the Perl Debugger to enter "single step mode" when this command is |
127 | encountered (it has no effect when Perl is run without the C<-d> flag). |
128 | |
d0496197 |
129 | B<NOTE:> The C<DB> here is the Perl Debugger, not the DB model. |
130 | |
d442cc9f |
131 | To now run the Catalyst development server under the Perl debugger, simply |
132 | prepend C<perl -d> to the front of C<script/myapp_server.pl>: |
133 | |
134 | $ perl -d script/myapp_server.pl |
135 | |
136 | This will start the interactive debugger and produce output similar to: |
137 | |
138 | $ perl -d script/myapp_server.pl |
139 | |
140 | Loading DB routines from perl5db.pl version 1.27 |
141 | Editor support available. |
142 | |
143 | Enter h or `h h' for help, or `man perldebug' for more help. |
144 | |
145 | main::(script/myapp_server.pl:14): my $debug = 0; |
146 | |
147 | DB<1> |
148 | |
149 | Press the C<c> key and hit C<Enter> to continue executing the Catalyst |
150 | development server under the debugger. Although execution speed will be |
151 | slightly slower than normal, you should soon see the usual Catalyst |
152 | startup debug information. |
153 | |
154 | Now point your browser to L<http://localhost:3000/books/list> and log |
155 | in. Once the breakpoint is encountered in the |
156 | C<MyApp::Controller::list> method, the console session running the |
157 | development server will drop to the Perl debugger prompt: |
158 | |
159 | MyApp::Controller::Books::list(/home/me/MyApp/script/../lib/MyApp/Controller/Books.pm:40): |
d0496197 |
160 | 40: $c->stash->{books} = [$c->model('DB::Books')->all]; |
d442cc9f |
161 | |
162 | DB<1> |
163 | |
164 | You now have the full Perl debugger at your disposal. First use the |
165 | C<next> feature by typing C<n> to execute the C<all> method on the Book |
166 | model (C<n> jumps over method/subroutine calls; you can also use C<s> to |
167 | C<single-step> into methods/subroutines): |
168 | |
169 | DB<1> n |
170 | SELECT me.id, me.authors, me.title, me.rating FROM books me: |
171 | MyApp::Controller::Books::list(/home/me/MyApp/script/../lib/MyApp/Controller/Books.pm:44): |
172 | 44: $c->stash->{template} = 'books/list.tt2'; |
173 | |
174 | DB<1> |
175 | |
176 | This takes you to the next line of code where the template name is set. |
177 | Notice that because we enabled C<DBIC_TRACE=1> earlier, SQL debug |
178 | output also shows up in the development server debug information. |
179 | |
180 | Next, list the methods available on our C<Book> model: |
181 | |
d0496197 |
182 | DB<1> m $c->model('DB::Books') |
d442cc9f |
183 | () |
184 | (0+ |
185 | (bool |
186 | MODIFY_CODE_ATTRIBUTES |
187 | _attr_cache |
188 | _collapse_result |
189 | _construct_object |
190 | _count |
191 | _result_class_accessor |
192 | _result_source_accessor |
193 | all |
194 | carp |
195 | <lines removed for brevity> |
196 | |
197 | DB<2> |
198 | |
199 | We can also play with the model directly: |
200 | |
d0496197 |
201 | DB<2> x ($c->model('DB::Books')->all)[1]->title |
d442cc9f |
202 | SELECT me.id, me.title, me.rating FROM books me: |
203 | 0 'TCP/IP Illustrated, Volume 1' |
204 | |
205 | This uses the Perl debugger C<x> command to display the title of a book. |
206 | |
207 | Next we inspect the C<books> element of the Catalyst C<stash> (the C<4> |
208 | argument to the C<x> command limits the depth of the dump to 4 levels): |
209 | |
210 | DB<3> x 4 $c->stash->{books} |
211 | 0 ARRAY(0xa8f3b7c) |
d0496197 |
212 | 0 MyApp::Model::DB::Book=HASH(0xb8e702c) |
d442cc9f |
213 | '_column_data' => HASH(0xb8e5e2c) |
214 | 'id' => 1 |
215 | 'rating' => 5 |
216 | 'title' => 'CCSP SNRS Exam Certification Guide' |
217 | '_in_storage' => 1 |
218 | <lines removed for brevity> |
219 | |
220 | Then enter the C<c> command to continue processing until the next |
221 | breakpoint is hit (or the application exits): |
222 | |
223 | DB<4> c |
224 | SELECT author.id, author.first_name, author.last_name FROM ... |
225 | |
226 | Finally, press C<Ctrl+C> to break out of the development server. |
227 | Because we are running inside the Perl debugger, you will drop to the |
228 | debugger prompt. Press C<q> to exit the debugger and return to your OS |
229 | shell prompt: |
230 | |
231 | DB<4> q |
232 | $ |
233 | |
234 | For more information on using the Perl debugger, please see C<perldebug> |
235 | and C<perldebtut>. You can also type C<h> or C<h h> at the debugger |
236 | prompt to view the built-in help screens. |
237 | |
238 | |
239 | =head1 DEBUGGING MODULES FROM CPAN |
240 | |
241 | Although the techniques discussed above work well for code you are |
242 | writing, what if you want to use print/log/warn messages or set |
243 | breakpoints in code that you have installed from CPAN (or in module that |
244 | ship with Perl)? One helpful approach is to place a copy of the module |
245 | inside the C<lib> directory of your Catalyst project. When Catalyst |
246 | loads, it will load from inside your C<lib> directory first, only |
247 | turning to the global modules if a local copy cannot be found. You can |
248 | then make modifications such as adding a C<$DB::single=1> to the local |
249 | copy of the module without risking the copy in the original location. |
250 | This can also be a great way to "locally override" bugs in modules while |
251 | you wait for a fix on CPAN. |
252 | |
253 | |
254 | Matt Trout has suggested the following shortcut to create a local |
255 | copy of an installed module: |
256 | |
257 | mkdir -p lib/Module; cp `perldoc -l Module::Name` lib/Module/ |
258 | |
3533daff |
259 | Note: If you are following along in Ubuntu, you will need to install |
260 | the C<perl-doc> package to use the C<perldoc> command. Use |
261 | C<sudo apt-get install perl-doc> to do that. |
262 | |
d442cc9f |
263 | For example, you could make a copy of |
264 | L<Catalyst::Plugin::Authentication|Catalyst::Plugin::Authentication> |
265 | with the following command: |
266 | |
267 | mkdir -p lib/Catalyst/Plugin; cp \ |
268 | `perldoc -l Catalyst::Plugin::Authentication` lib/Catalyst/Plugin |
269 | |
3533daff |
270 | You can then use the local copy inside your project to place logging |
271 | messages and/or breakpoints for further study of that module. |
272 | |
d442cc9f |
273 | B<Note:> Matt has also suggested the following tips for Perl |
274 | debugging: |
275 | |
276 | =over 4 |
277 | |
278 | =item * |
279 | |
280 | Check the version of an installed module: |
281 | |
282 | perl -MModule::Name -e 'print $Module::Name::VERSION;' |
283 | |
284 | For example: |
285 | |
286 | $ perl -MCatalyst::Plugin::Authentication -e \ |
287 | 'print $Catalyst::Plugin::Authentication::VERSION;' |
288 | 0.07 |
289 | |
290 | =item * |
291 | |
292 | Check if a modules contains a given method: |
293 | |
294 | perl -MModule::Name -e 'print Module::Name->can("method");' |
295 | |
296 | For example: |
297 | |
298 | $ perl -MCatalyst::Plugin::Authentication -e \ |
3533daff |
299 | 'print Catalyst::Plugin::Authentication->can("user");' |
d442cc9f |
300 | CODE(0x9c8db2c) |
301 | |
302 | If the method exists, the Perl C<can> method returns a coderef. |
303 | Otherwise, it returns undef and nothing will be printed. |
304 | |
305 | =back |
306 | |
307 | |
308 | =head1 AUTHOR |
309 | |
310 | Kennedy Clark, C<hkclark@gmail.com> |
311 | |
312 | Please report any errors, issues or suggestions to the author. The |
313 | most recent version of the Catalyst Tutorial can be found at |
d712b826 |
314 | L<http://dev.catalyst.perl.org/repos/Catalyst/trunk/Catalyst-Manual/lib/Catalyst/Manual/Tutorial/>. |
d442cc9f |
315 | |
45c7830f |
316 | Copyright 2006-2008, Kennedy Clark, under Creative Commons License |
d442cc9f |
317 | (L<http://creativecommons.org/licenses/by-nc-sa/2.5/>). |