http://qs321.pair.com?node_id=11144544

bliako has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks,

A Mojolicious app uses an external module (Mail::IMAPClient) which uses Carp which logs to STDERR. I need to tell Carp to use Mojoapp's own Mojo::Log object (which logs to a file with specific settings etc.).

many thanks, bliako

EDIT: I realised that Mail::IMAPClient outputs debug information as well and in its documentation it says that one can specify a filehandle to redirect just that *debug* output. In retrospect, this was my biggest problem when I asked this question. I stupidly thought all that debug output was going through Carp. For sending Carp's output to a (Mojo) logger, see solution below Re: Change Carp's output to Mojo::Log. For redirecting the debug output as well, I leave this as a reminder mostly to me (it is copypasted from Mojo::Log's and Mail::IMAPClient's doc):

# redirect Mail::IMAPClient to Mojo::Log's filehandle. use Mail::IMAPClient; use Mojo::Log; my $log = Mojo::Log->new(path => "logfile"); my $client = Mail::IMAPClient->new( ... Debug => 1, Debug_fh => $log->handle );

Replies are listed 'Best First'.
Re: Change Carp's output to Mojo::Log
by Corion (Patriarch) on Jun 09, 2022 at 10:31 UTC

    I'm not aware of something like this for Mojolicious, but I guess you can look at how Tk::Carp does its thing and do the same, except for Mojolicious.

Re: Change Carp's output to Mojo::Log
by haukex (Archbishop) on Jun 09, 2022 at 12:06 UTC

    If you look at the source of Mail::IMAPClient, you'll see this comment: "#local $SIG{__WARN__} = \&Carp::cluck; #DEBUG" which hints that the author uses $SIG{__WARN__} for this purpose (and Tk::Carp, pointed out by Corion, appears to work the same way). The following seems to work for me, though it's always worth noting that changes to $SIG{__WARN__} are global, so it's possible you might step on another module's toes or that one might step on yours. This is true even with local, unless you know exactly what the call stack looks like. You can of course limit the effects by using local $SIG{__WARN__} only in those blocks where you actually make calls to Mail::IMAPClient, that should help limit your exposure to such potential problems.

    use warnings; use strict; package Foo { use Carp; sub bar { carp "Foo Bar"; } } use Mojo::Log; my $log = Mojo::Log->new; local $SIG{__WARN__} = sub { $log->warn(@_) }; Foo::bar();

      i have seen that but I did not dare to use it (especially with Mojolicious). Thanks++ for clarifying.

Re: Change Carp's output to Mojo::Log
by mr_mischief (Monsignor) on Jun 09, 2022 at 13:35 UTC

    You already have some excellent advice. I'd be tempted to try using something like Capture::Tiny in the main program to wrap calls to the external module's code. It allows you to capture only stdout, only stderr, both merged, both separately, tee one or both (capture and send to the original destination), and all of this only for the scope of the coderef you choose.

    I have not tested the module with Mojo to be sure it works. I would think it's worth trying, as searching the web for the two together does not turn up any dire warnings.

Re: Change Carp's output to Mojo::Log
by Anonymous Monk on Jun 09, 2022 at 17:57 UTC