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
|
|
|
|
|
|
|
|