File Coverage

blib/lib/LWP/ConsoleLogger/Everywhere.pm
Criterion Covered Total %
statement 31 31 100.0
branch n/a
condition n/a
subroutine 10 10 100.0
pod 2 2 100.0
total 43 43 100.0


line stmt bran cond sub pod time code
1             package LWP::ConsoleLogger::Everywhere;
2 2     2   346561 use strict;
  2         13  
  2         63  
3 2     2   13 use warnings;
  2         4  
  2         79  
4              
5             our $VERSION = '1.000001';
6              
7 2     2   1150 use Class::Method::Modifiers ();
  2         3283  
  2         54  
8 2     2   926 use LWP::ConsoleLogger::Easy qw( debug_ua );
  2         9  
  2         20  
9 2     2   626 use Module::Runtime qw( require_module );
  2         11  
  2         23  
10 2     2   119 use Try::Tiny qw( try );
  2         5  
  2         91  
11 2     2   17 use Log::Dispatch ();
  2         9  
  2         39  
12 2     2   18 no warnings 'once';
  2         6  
  2         814  
13              
14             my $loggers;
15             my $dispatch_logger;
16              
17             {
18             my $key = "LWPCL_LOGFILE";
19             if ( exists $ENV{$key} && $ENV{$key} ) {
20             my $filename = $ENV{$key};
21             $dispatch_logger = Log::Dispatch->new(
22             outputs => [
23             [ 'File', min_level => 'debug', filename => $filename ],
24             ],
25             );
26             }
27             }
28              
29             my $code_injection = sub {
30             my $orig = shift;
31             my $self = shift;
32              
33             my $ua = $self->$orig(@_);
34             my $debug_ua = debug_ua($ua);
35             $debug_ua->logger($dispatch_logger) if $dispatch_logger;
36             push @{$loggers}, $debug_ua;
37             return $ua;
38             };
39              
40             try {
41             require_module('LWP::UserAgent');
42             Class::Method::Modifiers::install_modifier(
43             'LWP::UserAgent', 'around',
44             'new' => $code_injection
45             );
46             };
47              
48             try {
49             require_module('Mojo::UserAgent');
50             Class::Method::Modifiers::install_modifier(
51             'Mojo::UserAgent', 'around',
52             'new' => $code_injection
53             );
54             };
55              
56             sub loggers {
57 2     2 1 2819 return $loggers;
58             }
59              
60             sub set {
61 1     1 1 813 my $class = shift;
62 1         2 my $setting = shift;
63              
64 1         2 foreach my $logger ( @{$loggers} ) {
  1         3  
65 8         242 $logger->$setting(@_);
66             }
67              
68 1         19 return;
69             }
70              
71             1;
72              
73             =pod
74              
75             =encoding UTF-8
76              
77             =head1 NAME
78              
79             LWP::ConsoleLogger::Everywhere - LWP tracing everywhere
80              
81             =head1 VERSION
82              
83             version 1.000001
84              
85             =head1 SYNOPSIS
86              
87             use LWP::ConsoleLogger::Everywhere;
88              
89             # somewhere deep down in the guts of your program
90             # there is some other module that creates an LWP::UserAgent
91             # and now it will tell you what it's up to
92              
93             # somewhere else you can access and fine-tune those loggers
94             # individually:
95             my $loggers = LWP::ConsoleLogger::Everywhere->loggers;
96             $loggers->[0]->pretty(0);
97              
98             # or all of them at once:
99             LWP::ConsoleLogger::Everywhere->set( pretty => 1);
100              
101             # Redact sensitive data for all user agents
102             $ENV{LWPCL_REDACT_HEADERS} = 'Authorization,Foo,Bar';
103             $ENV{LWPCL_REDACT_PARAMS} = 'seekrit,password,credit_card';
104              
105             # Or observe without changing your code
106             PERL5OPT="-MLWP::ConsoleLogger::Everywhere" carton install
107              
108             perl -MLWP::ConsoleLogger::Everywhere my-script.pl
109              
110             =head1 DESCRIPTION
111              
112             This module turns on L<LWP::ConsoleLogger::Easy> debugging for every L<LWP::UserAgent> or L<Mojo::UserAgent>
113             based user agent anywhere in your code. It doesn't matter what package or class it is in,
114             or if you have access to the object itself. All you need to do is C<use> this module
115             anywhere in your code and it will work.
116              
117             You can access and configure the loggers individually after they have been created
118             using the C<loggers> class method. To change all of them at once, use the C<set> class
119             method instead.
120              
121             See
122             L<https://www.olafalders.com/2021/12/01/observing-network-traffic-with-lwp-consolelogger-everywhere/>
123             for a practical example of how to use this module.
124              
125             =head1 CLASS METHODS
126              
127             =head2 set( <setting> => <value> )
128              
129             LWP::ConsoleLogger::Everywhere->set( dump_content => 0 );
130              
131             This class method changes the given setting on all logger objects that have been created
132             so far. The first argument is the accessor name of the setting you want to change, and the
133             second argument is the new value. This cannot be used to access current values. See
134             L<LWP::ConsoleLogger#SUBROUTINES/METHODS> for what those settings are.
135              
136             =head2 loggers
137              
138             my $loggers = LWP::ConsoleLogger::Everywhere->loggers;
139             foreach my $logger ( @{ $loggers } ) {
140             # stop dumping headers
141             $logger->dump_headers( 0 );
142             }
143              
144             This class method returns an array reference of all L<LWP::ConsoleLogger> objects that have
145             been created so far, with the newest one last. You can use them to fine-tune settings. If there
146             is more than one user agent in your application you will need to figure out which one is which.
147             Since this is for debugging only, trial and error is a good strategy here.
148              
149             =head1 ENVIRONMENT VARIABLES
150              
151             =head2 LWPCL_LOGFILE
152              
153             By default all data will be dumped to your console (as the name of this module implies) using
154             L<Log::Dispatch>. You may change this behavior though. The general approach is to do it from
155             within your script, for example like this:
156              
157             use LWP::ConsoleLogger::Everywhere;
158             my $loggers = LWP::ConsoleLogger::Everywhere->loggers;
159             my $log_dispatch = Log::Dispatch->new(
160             outputs => [
161             [ 'File', min_level => 'debug', filename => 'log_file.txt' ],
162             [ 'Screen', min_level => 'debug' ],
163             ],
164             );
165             foreach my $logger ( @{ $loggers } ) {
166             $logger->logger($log_dispatch);
167             }
168              
169             The second approach is simpler and is done via an environment variable, for example you can run
170             your script like this:
171              
172             LWPCL_LOGFILE=foo.log perl -MLWP::ConsoleLogger::Everywhere foo.pl
173              
174             this will be equivalent to the first approach with the following Log::Dispatch logger:
175              
176             my $log_dispatch = Log::Dispatch->new(
177             outputs => [ [ 'File', min_level => 'debug', filename => 'foo.log' ] ],
178             );
179              
180             =head1 CAVEATS
181              
182             If there are several different user agents in your application, you will get debug
183             output from all of them. This could be quite cluttered.
184              
185             Since L<LWP::ConsoleLogger::Everywhere> does its magic during compile time it will
186             most likely catch every user agent in your application, unless
187             you C<use LWP::ConsoleLogger::Everywhere> inside a file that gets loaded at runtime.
188             If the user agent you wanted to debug had already been created at that time it
189             cannot hook into the constructor any more.
190              
191             L<LWP::ConsoleLogger::Everywhere> works by catching new user agents directly in
192             L<LWP::UserAgent> when they are created. That way all properly implemented sub classes
193             like L<WWW::Mechanize> will go through it. But if you encounter one that installs its
194             own handlers into the user agent after calling C<new> in L<LWP::UserAgent>
195             that might overwrite the ones L<LWP::ConsoleLogger> installed.
196              
197             L<LWP::ConsoleLogger::Everywhere> will keep references to all user agents that were
198             ever created during for the lifetime of your application. If you have a lot of lexical
199             user agents that you recycle all the time they will not actually go away and might
200             consume memory.
201              
202             =head1 SEE ALSO
203              
204             For more information or if you want more detailed control see L<LWP::ConsoleLogger>.
205              
206             =head1 AUTHOR
207              
208             Olaf Alders <olaf@wundercounter.com>
209              
210             =head1 COPYRIGHT AND LICENSE
211              
212             This software is Copyright (c) 2014 by MaxMind, Inc.
213              
214             This is free software, licensed under:
215              
216             The Artistic License 2.0 (GPL Compatible)
217              
218             =cut
219              
220             __END__
221              
222             # ABSTRACT: LWP tracing everywhere
223