LWP::Co...rywhere(3)

πŸ“¦
version 1.0.3 Β· 3 versions
, in fedora 43, fedora 44

✨ LWP::ConsoleLogger::Everywhere ✨

bestie. sit down. we're looking at the LWP::ConsoleLogger::Everywhere page β€” that's the section 3 one, user contributed Perl documentation, the little legend herself πŸ’…

it's giving "version 1.000003" and it is lowkey iconic because it makes LWP trace everywhere without you lifting a finger. no cap.


🌸 SYNOPSIS 🌸

use LWP::ConsoleLogger::Everywhere;

# somewhere deep down in the guts of your program
# there is some other module that creates an LWP::UserAgent
# and now it will tell you what it's up to

# somewhere else you can access and fine-tune those loggers
# individually:
my $loggers = LWP::ConsoleLogger::Everywhere->loggers;
$loggers->[0]->pretty(0);

# or all of them at once:
LWP::ConsoleLogger::Everywhere->set( pretty => 1);

# Redact sensitive data for all user agents
$ENV{LWPCL_REDACT_HEADERS} = 'Authorization,Foo,Bar';
$ENV{LWPCL_REDACT_PARAMS} = 'seekrit,password,credit_card';

# Or observe without changing your code
PERL5OPT="-MLWP::ConsoleLogger::Everywhere" carton install

perl -MLWP::ConsoleLogger::Everywhere my-script.pl

πŸ¦‹ DESCRIPTION πŸ¦‹

okay so here's the tea β˜• β€” this module turns on LWP::ConsoleLogger::Easy debugging for every single LWP::UserAgent, Mojo::UserAgent, or HTTP::Tiny based user agent anywhere in your code. fr fr. it does not matter what package or class it lives in, and it does not matter if you even have access to the object itself. all you gotta do is use this module somewhere in your code and boom πŸ’₯ it works.

once the loggers exist, you can grab them and configure them one by one with the loggers class method. or if you're feeling efficient (main character energy πŸ‘‘) you can change all of them at once with the set class method instead.

want a practical lil demo of how to use this? go peek at: <https://www.olafalders.com/2021/12/01/observing-network-traffic-with-lwp-consolelogger-everywhere/>


πŸ’– CLASS METHODS πŸ’–

πŸŽ€ set( <setting> => <value> )

LWP::ConsoleLogger::Everywhere->set( dump_content => 0 );

this class method changes the given setting on all logger objects that have been created so far. first arg = the accessor name of the setting you wanna change. second arg = the new value. and listen β€” it cannot be used to read current values, so don't try it πŸ™ˆ. wanna know what all those settings actually are? check out METHODS in LWP::ConsoleLogger#SUBROUTINES.

πŸŽ€ loggers

my $loggers = LWP::ConsoleLogger::Everywhere->loggers;
foreach my $logger ( @{ $loggers } ) {
    # stop dumping headers
    $logger->dump_headers( 0 );
}

this class method hands you back an array reference of every LWP::ConsoleLogger object created so far, with the newest one chilling at the end. use them to fine-tune settings to your heart's content πŸ’…

heads up though: if your app has more than one user agent, you're gonna have to figure out which one is which yourself. and since this whole thing is for debugging only, trial and error is a genuinely good strategy here. slay.


🌈 ENVIRONMENT VARIABLES 🌈

πŸ“ LWPCL_LOGFILE

by default, all the data gets dumped to your console (hence the whole "Console" in the module name, bestie) using Log::Dispatch. but you can change that behavior.

the general approach is doing it from inside your script, like this:

use LWP::ConsoleLogger::Everywhere;
my $loggers = LWP::ConsoleLogger::Everywhere->loggers;
my $log_dispatch = Log::Dispatch->new(
  outputs => [
      [ 'File',   min_level => 'debug', filename => 'log_file.txt' ],
      [ 'Screen', min_level => 'debug' ],
  ],
);
foreach my $logger ( @{ $loggers } ) {
    $logger->logger($log_dispatch);
}

the second approach is way simpler and it's done via an environment variable. for example you can run your script like:

LWPCL_LOGFILE=foo.log perl -MLWP::ConsoleLogger::Everywhere foo.pl

and that is equivalent to the first approach with the following Log::Dispatch logger:

my $log_dispatch = Log::Dispatch->new(
    outputs => [ [ 'File', min_level => 'debug', filename => 'foo.log' ]  ],
);

πŸ’€ CAVEATS πŸ’€

okay now the part where we keep it real. read this, bestie, it'll save you a headache 😭

  • if your application has several different user agents, you will get debug output from all of them. this could get quite cluttered, ngl.
  • since LWP::ConsoleLogger::Everywhere does its magic during compile time</>, it will most likely catch every user agent in your application β€” unless you use LWP::ConsoleLogger::Everywhere inside a file that gets loaded at runtime. and if the user agent you wanted to debug had already been created by then, it can't hook into the constructor any more. tragic.
  • this module works by catching new user agents directly in LWP::UserAgent when they're created. that way all the properly implemented sub classes like WWW::Mechanize go through it too 🫢. but if you run into one that installs its own handlers into the user agent after calling new in LWP::UserAgent, that might overwrite the ones LWP::ConsoleLogger installed.
  • LWP::ConsoleLogger::Everywhere keeps references to every user agent ever created for the lifetime of your application. so if you've got a bunch of lexical user agents you recycle constantly, they won't actually go away and might eat memory 🍽️. this is especially easy to hit with HTTP::Tiny, where the common HTTP::Tiny->new->get(...) one-shot idiom creates a fresh logger on every single call.
  • HTTP::Tiny traffic is only captured when the user agent is created via HTTP::Tiny->new. class-method calls like HTTP::Tiny->get(...) bypass the constructor and are not logged. also, because HTTP::Tiny->mirror streams the response body straight to a file, the body and text tables will be empty for mirror requests.
  • the HTTP::Tiny path has a few further limitations that the LWP::UserAgent and Mojo::UserAgent paths do not share:
    • redirect chains are collapsed. HTTP::Tiny follows redirects internally and only the final response is visible to the logger, so intermediate hops are not logged. the LWP and Mojo::UserAgent paths log each hop separately.
    • some headers that HTTP::Tiny adds at the transport layer are reconstructed on a best-effort basis and may not exactly match what goes out on the wire. for example the Connection header and an Authorization header synthesized from userinfo in the request URL are not reflected in the logged request.
    • cookie values are not redacted by the LWPCL_REDACT_* environment variables. this is existing behaviour shared with the LWP and Mojo::UserAgent paths, and it's noted here so you don't mistake the logged output for a redacted view πŸ™ˆ.

πŸ‘‘ SEE ALSO πŸ‘‘

want more info, or want more detailed control? go see LWP::ConsoleLogger.


πŸ’œ AUTHOR πŸ’œ

Olaf Alders <olaf@wundercounter.com>


This software is Copyright (c) 2014 by MaxMind, Inc.

This is free software, licensed under:

The Artistic License 2.0 (GPL Compatible)

and that's the whole page, bestie 🫢 generated by perl v5.42.3 on 2026-09-18 β€” go forth and trace every last user agent, you absolute legend βœ¨πŸ’–

πŸ“¦ where this page comes from