File Coverage

blib/lib/Fred/Fish/DBUG/Tutorial.pm
Criterion Covered Total %
statement 12 12 100.0
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 16 16 100.0


line stmt bran cond sub pod time code
1             ###
2             ### Copyright (c) 2019 - 2025 Curtis Leach. All rights reserved.
3             ###
4             ### Module: Fred::Fish::DBUG::Tutorial
5              
6             package Fred::Fish::DBUG::Tutorial;
7              
8 1     1   130496 use strict;
  1         4  
  1         39  
9 1     1   17 use warnings;
  1         6  
  1         106  
10              
11 1     1   10 use vars qw ( @ISA @EXPORT @EXPORT_OK $VERSION );
  1         2  
  1         94  
12 1     1   7 use Exporter;
  1         13  
  1         288  
13              
14             $VERSION = "2.10";
15             @ISA = qw ( Exporter );
16             @EXPORT = qw ();
17             @EXPORT_OK = qw ();
18              
19             # =============================================================================
20             # Only POD text appears below this line!
21             # =============================================================================
22              
23             =head1 NAME
24              
25             Fred::Fish::DBUG::Tutorial - Gives a basic tutorial on how to use the
26             L module.
27              
28             =head1 SYNOPSIS
29              
30             This is real "old school" technology. So it's fairly obvious on how to use it.
31             It's basically the next step up from just putting print STDERR calls in your
32             code. But in this case you don't have to remember to remove the debug prints
33             from the code before releasing it into production. The logging is always
34             available on an on demand basis!
35              
36             In many cases it's just easier to show an example instead of trying to put
37             things into words. So this module is just some POD text to document how to use
38             L.
39              
40             For more details on how to use a function mentioned in this POD text see
41             I. The POD you are reading right now just gives
42             you the basics, not the advanced options available. There is a lot of extra
43             functionality not covered here.
44              
45             =head1 BASIC USAGE
46              
47             In order to get anything to write to your B logs, you must first call
48             I. If you never call it then nothing will be written to your
49             B logs. It won't even create an empty file.
50              
51             Also if you call it more than once, all subsequent calls to DBUG_PUSH() are
52             ignored. Only the 1st call is honored!
53              
54             There are many interesting optional arguments to DBUG_PUSH() so read the POD
55             on it for more details!
56              
57             The following are all examples for a program called B. It's
58             assumed it's called like:
59              
60             example.pl -a -b
61              
62             =head1 EXAMPLE # 1 - a really simple example.
63              
64             use Fred::Fish::DBUG qw / on /;
65             DBUG_PUSH ($file); # Assuming $file is already set.
66             DBUG_ENTER_FUNC (@ARGV);
67             DBUG_LEAVE (0);
68              
69             Here's what's written to your B logs. Notice how it put square brackets
70             around each argument to your program and made it a comma separated list.
71              
72             >main-prog
73             | args: [-a], [-b]
74            
75             exit (0)
76              
77             >Fred::Fish::DBUG::END
78             | Fred::Fish::DBUG: So Long, and Thanks for All the Fish!
79            
80              
81             ===============================================================
82              
83             =head1 EXAMPLE # 2 - Another simple example!
84              
85             use Fred::Fish::DBUG qw / on /;
86             my $flag = 1;
87             DBUG_PUSH ($file, off=>${flag}); # Assuming $file is already set.
88             DBUG_ENTER_FUNC (@ARGV);
89             DBUG_LEAVE (0);
90              
91             Wait, what happened? There is no B output!
92              
93             The B argument said to turn B off. If you'd set I<$flag> to B<0>
94             instead of B<1>, it would have turned B back on again. So if you had the
95             value of I<$flag> controlled by an argument to your program, or by a special
96             environment variable, you could decide at run time if you are going to generate
97             a B log or not.
98              
99             You could have done the same thing by putting the call to DBUG_PUSH() into an
100             B block, but that's a bit more typing and messy.
101              
102             ===============================================================
103              
104             =head1 EXAMPLE # 3 - Yet another simple example!
105              
106             use Fred::Fish::DBUG qw / off /;
107             DBUG_PUSH ($file); # Assuming $file is already set.
108             DBUG_ENTER_FUNC (@ARGV);
109             DBUG_LEAVE (0);
110              
111             Oops, no B logs again. This time B has been completely disabled.
112             Nothing will be logged. You did notice the change from B to B.
113              
114             ===============================================================
115              
116             =head1 EXAMPLE # 4 - Some conditional logic.
117              
118             use Fred::Fish::DBUG qw / on_if_set env_var_of_your_choice /;
119              
120             If ( B<$ENV{env_var_of_your_choice}> ) is true it will behave like EXAMPLE # 1
121             & 2, otherwise it will behave like EXAMPLE # 3.
122              
123             use Fred::Fish::DBUG qw / off_if_set env_var_of_your_choice /;
124              
125             If ( B<$ENV{env_var_of_your_choice}> ) is true it will behave like EXAMPLE # 3,
126             otherwise it will behave like EXAMPLE # 1 & 2.
127              
128             As it's name implies B can be any name you want.
129             Provides an easy way to take your module out of the B trace even when
130             other code currently has B active. Allows someone to see only his own
131             code without having your module cluttering up his logs uless he requests to see
132             it by setting the appropriate ENV var.
133              
134             ===============================================================
135              
136             =head1 EXAMPLE # 5 - Something a little more advanced.
137              
138              
139             use Fred::Fish::DBUG qw / on /;
140             DBUG_PUSH ($file); # Assuming $file is already set.
141             DBUG_ENTER_FUNC (@ARGV);
142             my ($a, $b);
143             my @pass = qw /1 2 3/;
144             some_function ( qw /Once upon a time!/ );
145             $a = some_function ( "There were", 3, "little pigs.", "?@*!*#****" );
146             my @names = some_function ( qw /Larry Joe Curly/ );
147             ($a, $b) = some_function ( @pass, \@pass, undef );
148             DBUG_LEAVE (0);
149              
150             sub some_function {
151             DBUG_ENTER_FUNC (@_);
152             # Do some unspecified work here!
153             DBUG_RETURN (@_);
154             }
155              
156             Here's what's written to your B logs. See the return values are also
157             surrounded by square brackets in a comma separated list. Also see how what's
158             returned is controlled by what you plan on doing with the return value. Toss
159             it, saving as a scalar, and asking for all or part of the array!
160              
161             The return basically evaluates as:
162              
163             return ( wantarray ? @_ : (defined wantarray ? $_[0] : undef) );
164              
165             >main-prog
166             | args: [-a], [-b]
167             | >main::some_function
168             | | args: [Once], [upon], [a], [time!]
169             |
170             | >main::some_function
171             | | args: [There were], [3], [little pigs.], [?@*!*#****]
172             |
173             | >main::some_function
174             | | args: [Larry], [Joe], [Curly]
175             |
176             | >main::some_function
177             | | args: [1], [2], [3], [ARRAY(0x2013bd78)], []
178             | ])
179            
180             exit (0)
181              
182             >Fred::Fish::DBUG::END
183             | Fred::Fish::DBUG: So Long, and Thanks for All the Fish!
184            
185              
186             Some special notes about the 4th call to some_function.
187              
188             It sets $a to "1" and $b to "2". The rest of the return values are tossed.
189             Since ($a, $b) just asks for the 1st 2 values in the returned array! Too bad
190             perl doesn't provide a way to tell how many of the values are actually used.
191             All perl's B feature says is to expect zero, one or many return
192             values. So this module can't tell you that these extra values are being tossed
193             and not show these extra unused values in the B logs!
194              
195             Another note is that it doesn't attempt to expand array or hash references.
196             You'd have to do that yourself if you want to see it in B.
197              
198             But it does convert a code reference into the name of the function. That
199             information is just too useful when it happens.
200              
201             Ex: some_function ( \&call_me );
202              
203             The argument would show up as:
204              
205             | | args: [\&main::call_me]
206              
207             Finally note the final EundefE in both the args and return value.
208             You'll see this whenever an undefined value is passed this way so that the
209             value won't be mistaken for the empty string. So you're out of luck if you
210             expect to see this value as a string in your data and know which is which.
211              
212             ===============================================================
213              
214             =head1 EXAMPLE # 6 - Lets do some printing ...
215              
216             use Fred::Fish::DBUG qw / on /;
217             DBUG_PUSH ($file, kill_end_trace => 1); # Assuming $file is already set.
218             DBUG_ENTER_FUNC (@ARGV);
219             some_function ( qw /Once upon a time!/ );
220             DBUG_LEAVE (0);
221              
222             sub some_function {
223             DBUG_ENTER_FUNC (@_);
224             DBUG_PRINT ("INFO", "<%s> <%s>", "Hello", "World!");
225             DBUG_PRINT ("WARN", "<%s> <%s>", "Goodbye!");
226             DBUG_PRINT ("DBUG", "<%s> <%s>");
227             $msg = DBUG_PRINT ("TRICK", "one", "two", "three");
228             DBUG_VOID_RETURN ();
229             }
230              
231             Here's what's written to your B logs. Note that the B
232             option stopped the printing of the B block info after DBUG_LEAVE() was
233             called. This would include any of your own B blocks as well.
234              
235             >main-prog
236             | args: [-a], [-b]
237             | >main::some_function
238             | | args: [Once], [upon], [a], [time!]
239             | | INFO:
240             | | WARN: <>
241             | | DBUG: <%s> <%s>
242             | | TRICK: one
243             |
244            
245             exit (0)
246              
247             Now for some fun facts about the above B trace. The WARN line had
248             generated a warning due to the missing 2nd value. Which we could have trapped
249             if we wanted to via DBUG_TRAP_SIGNAL or DBUG_TIE_STDERR.
250              
251             Since the DBUG line had no arguments it didn't interpret it as a format string.
252             And the TRICK line just printed "one" since it didn't include any formatting
253             information to process the other arguments with. It doesn't mash them together
254             like S> would have. And $msg was set to
255             S<"one\n">.
256              
257             ===============================================================
258              
259             =head1 EXAMPLE # 7 - What happens if you call die in your function?
260              
261             sub some_function {
262             DBUG_ENTER_FUNC (@_);
263             die ("Die you dirty rotten scoundrel!\n");
264             DBUG_PRINT ("INFO", "Did you miss me?");
265             DBUG_RETURN (@_);
266             }
267              
268             Here's what's written to your B logs.
269              
270             >main-prog
271             | args: [-a], [-b]
272             | >main::some_function
273             | | args: [Once], [upon], [a], [time!]
274              
275             >Fred::Fish::DBUG::END
276             | Fred::Fish::DBUG: So Long, and Thanks for All the Fish!
277             | Fred::Fish::DBUG: Exit Status (255)
278            
279              
280             If you want your die message also written to fish, see DBUG_TRAP_SIGNAL or
281             DBUG_TIE_STDERR for how to do that as well. That's not covered here!
282              
283             ===============================================================
284              
285             =head1 EXAMPLE # 8 - What happens if your die calls are trapped by eval or try?
286              
287             use Try::Tiny;
288             ...
289             some_function (); # Called from your main program ...
290             ...
291              
292             sub some_function {
293             DBUG_ENTER_FUNC (@_);
294             eval {
295             die_function (1);
296             };
297             eval {
298             help_me_die ();
299             };
300             try {
301             die_function (2);
302             };
303              
304             DBUG_PRINT ("INFO", "So are we ready to die yet?");
305             die ("So die already!\n");
306             DBUG_VOID_RETURN (); # We never get here!
307             }
308              
309             sub die_function {
310             DBUG_ENTER_FUNC (@_);
311             die ("I want to die!\n");
312             DBUG_VOID_RETURN (); # We never get here!
313             }
314              
315             sub help_me_die {
316             DBUG_ENTER_FUNC (@_);
317             die_function (@_);
318             DBUG_VOID_RETURN (); # We never get here!
319             }
320              
321             See how the fish logs auto-balance themselves after each die was trapped! Older
322             releases of this module couldn't do this and required the use of DBUG_CATCH() to
323             do this. If used today all it would do is change the Auto-balancing message.
324             See the POD for more info and why it's still around.
325              
326             >main-prog
327             | args: [-a], [-b]
328             | >main::some_function
329             | | >main::die_function
330             | | | args: [1]
331             | |
332             | | >main::help_me_die
333             | | | >main::die_function
334             | | |
335             | |
336             | | >main::die_function
337             | | | args: [2]
338             | |
339             | | INFO: So are we ready to die yet?
340              
341             >Fred::Fish::DBUG::END
342             | Fred::Fish::DBUG: So Long, and Thanks for All the Fish!
343             | Fred::Fish::DBUG: Exit Status (255)
344            
345              
346              
347             ===============================================================
348              
349             =head1 EXAMPLE # 9 - So it rebalances. What if I forget to put in the RETURN?
350              
351             # Called from your main program ...
352             ...
353             some_function (qw /a b c/);
354             some_function (qw /x y z/);
355             some_function (qw /1 2 3/);
356             ...
357              
358             sub some_function {
359             DBUG_ENTER_FUNC (@_);
360             }
361              
362             See how the B logs got confused because of this. There is no way to
363             auto-correct for this type of misuse of the module. You have to figure out
364             yourself where the missing DBUG_RETURN call belonged!
365              
366             >main-prog
367             | args: [-a], [-b]
368             | >main::some_function
369             | | args: [a], [b], [c]
370             | | >main::some_function
371             | | | args: [x], [y], [z]
372             | | | >main::some_function
373             | | | | args: [1], [2], [3]
374             | | |
375             exit (0)
376              
377             >Fred::Fish::DBUG::END
378             | Fred::Fish::DBUG: So Long, and Thanks for All the Fish!
379            
380              
381             This problem doesn't necessarily mean your code isn't working. It just proves
382             you have an issue writing to B. And you might not be able to use the
383             B logs to prove your code is working as expected!
384              
385             But what about that last return in B before the exit? That return was
386             done by the call to DBUG_LEAVE() that was assumed by the example.
387              
388             ===============================================================
389              
390             =head1 EXAMPLE # 10 - Misusing the RETURN functions ...
391              
392             Please remember that this module is a collection of functions. It can't do
393             a return for you. There is a bug in this code. Can you see it?
394              
395             ...
396             my @array = some_function (qw /a b c/);
397             DBUG_PRINT ("WARN", "Do you see it now?");
398             ...
399              
400             sub some_function {
401             DBUG_ENTER_FUNC (@_);
402              
403             # I'll leave it as an exercise on why I used BLOCK vs FUNC here!
404             # Try it out yourself if you dare!
405             foreach ( qw / One Two Three / ) {
406             DBUG_ENTER_BLOCK ("LOOP", $_); # Naming this foreach code block!
407             DBUG_VOID_RETURN (); # This is OK.
408             }
409              
410             unless ( 0 ) {
411             DBUG_ENTER_BLOCK ("NEVER"); # Naming this unless code block!
412             DBUG_VOID_RETURN (); # This is OK.
413             }
414              
415             if ( 1 ) {
416             DBUG_RETURN (@_); # The bug!
417             }
418              
419             DBUG_PRINT ("WARN", "Did you notice what the mistake was?");
420              
421             DBUG_RETURN (reverse @_); # This is OK!
422             }
423              
424             Hopefully looking at the B trace below made it obvious what the bug was.
425             And this most likely represents a real logic bug in your code. Not just a
426             problem writing to the B log correctly like in the previous example.
427              
428             >main-prog
429             | args: [-a], [-b]
430             | >main::some_function
431             | | args: [a], [b], [c]
432             | | >>LOOP
433             | | | args: [One]
434             | | <
435             | | >>LOOP
436             | | | args: [Two]
437             | | <
438             | | >>LOOP
439             | | | args: [Three]
440             | | <
441             | | >>NEVER
442             | | <
443             |
444             | WARN: Did you notice what the mistake was?
445            
446             WARN: Do you see it now?
447             < *** Unbalanced Returns *** Potential bug in your code!
448             exit (0)
449              
450             >Fred::Fish::DBUG::END
451             | Fred::Fish::DBUG: So Long, and Thanks for All the Fish!
452            
453              
454             Still didn't see it? The B block should have done
455             S<"B DBUG_RETURN(@_);"> It wasn't actually returning control to the
456             caller as expected! We could have put a return before the last S
457             as well, but perl already assumes the last line of a function provides the
458             return value.
459              
460             The DBUG_VOID_RETURN in the foreach and unless blocks are OK. All it's doing
461             is terminating a block of code that we named. It's not expected to do an actual
462             return. I'm just treating them as virtual functions in the B logs!
463              
464             I could even had done S<@a = DBUG_RETURN ($a, $b, $c, $d>) to end the foreach
465             loop so that I could log the progress of the loop as it cycled through the
466             code over and over again. In this case the S> is important, otherwise
467             the caller of the function dictates what gets written to B. When we
468             actually want to always see the entire list.
469              
470             ===============================================================
471              
472             =head1 EXAMPLE # 11 - What about the special BEGIN/END functions?
473              
474             use Fred::Fish::DBUG;
475             DBUG_PUSH ($file); # Assuming $file is already set.
476             DBUG_ENTER_FUNC (@ARGV);
477             DBUG_LEAVE (0);
478             BEGIN {
479             DBUG_ENTER_FUNC (@_);
480             DBUG_VOID_RETURN ();
481             }
482             END {
483             DBUG_ENTER_FUNC (@_);
484             DBUG_VOID_RETURN ();
485             }
486              
487             Gives the following B log.
488              
489             >main-prog
490             | args: [-a], [-b]
491            
492             exit (0)
493              
494             >main::END
495            
496              
497             >Fred::Fish::DBUG::END
498             | Fred::Fish::DBUG: So Long, and Thanks for All the Fish!
499            
500              
501             What happened to the tracing of the BEGIN block of code?
502              
503             BEGIN was called before you called DBUG_PUSH(), so it wasn't tracked in the
504             B log. You'd need to call DBUG_PUSH() in the BEGIN block itself if you'd
505             like B to trace your BEGIN logic.
506              
507             And speaking of BEGIN, never, ever call DBUG_TRAP_SIGNAL in a BEGIN block. You
508             can get really strange behavior if you have syntax errors in your code and these
509             error messages and warnings get trapped by L. The only reason
510             to call it in a BEGIN block is to stress test L itself.
511              
512             As a final note, except for AUTOLOAD, these and the other special Perl functions
513             have no caller, arguments or return values. They are called by Perl itself and
514             not by your code. Like BEGIN at compile time and END when Perl is shutting down
515             your code.
516              
517             ===============================================================
518              
519             =head1 EXAMPLE # 12 - Some not so obvious surprises ...
520              
521             Or maybe not if you've been paying close attention.
522              
523             For all examples below assume:
524              
525             sub some_function {
526             DBUG_ENTER_FUNC (@_);
527             DBUG_RETURN (@_);
528             }
529              
530             ********************
531              
532             if ( some_function ( qw /1 0 -1/ ) ) { ... }
533             if ( some_function ( qw /1 0 -1/ ) == 0 ) { ... }
534              
535             The interesting part, both calls log the same return value to B.
536              
537             |
538              
539             It was smart enough to tell it to return just the first value instead of a list
540             of values.
541              
542             ********************
543              
544             foreach ( some_function ( qw /1 0 -1/ ) ) { ... }
545              
546             The interesting part of the B log:
547              
548             |
549              
550             Notice it was smart enough to return a list of values. And the loop had three
551             iterations.
552              
553             ********************
554              
555             while ( some_function ( qw /1 0 -1/ ) ) { ... }
556              
557             The interesting part of the B log:
558              
559             |
560              
561             It was smart enough to tell it to return just the first value instead of a list
562             of values. But you ended up in an infinite loop!
563              
564             ********************
565              
566             $val = ( some_function ( qw / a b c / ) )[1];
567              
568             The interesting part of the B log:
569              
570             |
571              
572             And B<$val> gets set to "b"!
573              
574             ********************
575              
576             my $x = call_me ( some_function ( qw /a b c/ ) );
577              
578             The interesting part of the B log:
579              
580             |
581             | >main::call_me
582             | | args: [a], [b], [c]
583             |
584              
585             Notice that B returned all it's return values as arguments to
586             B!
587              
588             ********************
589              
590             Which leads us to this final surprising result. Which should be obvious, but
591             usually isn't at first glance.
592              
593             call_me (qw /a b c/);
594             $x = call_me (qw /a b c/);
595             @l = call_me (qw /a b c/);
596              
597             sub call_me {
598             DBUG_ENTER_FUNC (@_);
599             DBUG_RETURN ( some_function (@_) );
600             }
601              
602             The call to B will always return in list mode! No matter what it
603             finally decides to return for B! It doesn't inherit the I
604             status!
605              
606             | |
607              
608             It treats DBUG_RETURN() as just another function call! Which can be a bit
609             counterintuitive at times! So if you wanted B to inherit the
610             I status of B, you'd have to do something like this.
611              
612             sub call_me {
613             DBUG_ENTER_FUNC (@_);
614             if ( wantarray ) {
615             return DBUG_RETURN (some_function (@_));
616             } elsif ( defined wantarray ) {
617             return DBUG_RETURN (scalar some_function (@_));
618             } else {
619             some_function (@_);
620             return DBUG_VOID_RETURN ();
621             }
622             }
623              
624             In this example B would write to B one of the following 3
625             cases, depending on how B was called.
626              
627             | |
628             | |
629             | |
630              
631             In most cases this distinction makes no difference, it can just be a bit of a
632             surprise.
633              
634             But what if B did some monkey business like B does?
635             Where list mode returns a list of integers representing the various parts of the
636             date/time. While in scalar mode it returns the entire date/time as a single
637             string. Then you'd have to implement the work around shown above if you didn't
638             want to return that 1st integer in scalar mode.
639              
640             See DBUG_RETURN_SPECIAL() if you'd like to implement something like B
641             yourself and hide the complex return logic. All it does is allow you to
642             easily customize what's returned in scalar mode.
643              
644             ===============================================================
645              
646             =head1 IN CONCLUSION
647              
648             This should help get you started using this module. Just remember that only the
649             call to DBUG_PUSH was required. Everything else is optional! You can even
650             trace just some functions, you don't have to trace them all.
651              
652             There were many features not covered by this tutorial that you could find
653             useful.
654              
655             Such as:
656              
657             * Trapping signals for logging to fish.
658             * Trapping STDOUT/STDERR for logging to fish.
659             * Masking passwords and other sensitive arguments to your function.
660             * Masking passwords and other sensitive return values.
661             * Temporarily pausing fish's output when fish just gets too verbose.
662             * Filtering your fish output.
663             * Using color in your fish logs.
664             * Handling multi-threading programs in a single fish log.
665             * Handling multi-processing in a single fish log.
666             * Auto-deleting your fish file if your program exits with status zero,
667             and keeping it for all other exit status codes. So you can easily
668             detect and debug your rare failure cases without filling up your disk
669             with logs on success.
670             * Admin funcs like ASSERT, ACTIVE, and EXECUTE.
671             * And much, much more ...
672              
673             This is only the beginning! :)
674              
675              
676             =head1 COPYRIGHT
677              
678             Copyright (c) 2019 - 2025 Curtis Leach. All rights reserved.
679              
680             This program is free software. You can redistribute it and/or modify it under
681             the same terms as Perl itself.
682              
683              
684             =head1 SEE ALSO
685              
686             L - The module we are talking about in this POD. The one
687             you should be using.
688              
689             L - Does the actual work when fish is enabled.
690              
691             L - The stub version of the ON module.
692              
693             L - Allows you to trap and log STDOUT/STDERR to B.
694              
695             L - Allows you to trap and log signals to B.
696              
697             L - Allows you to implement action
698             DBUG_SIG_ACTION_LOG for B. Really dangerous to use. Will break most
699             code bases.
700              
701             L - A L wrapper to redirect test results to
702             B.
703              
704             =cut
705              
706             # ==============================================================
707             #required if module is included w/ require command;
708             1;