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