title: How can I use tie() to redirect STDOUT, STDERR only for certain packages?
body: <p>I need to work with some libraries that unfortunately log diagnostic
  messages to STDOUT and STDERR. By using <code>tie</code>, I can redirect those
  writes to a function that captures those. Since I don't want all
  STDOUT and STDERR output of my programs to be captured thtough the
  tied handle, I'd like to do this only for certain packages.</p>
  
  <p>I have come up with a solution where the actual behavior is determined
  by looking at caller() as can be seen below, but I have the feeling
  that there has to be a better way... Is there a more elegant solution?</p>
  
  <pre><code>package My::Log::Capture;
  use strict;
  use warnings;
  use 5.010;
  
  sub TIEHANDLE {
      my ($class, $channel, $fh, $packages) = @_;
      bless {
          channel =&gt; lc $channel,
          fh =&gt; $fh,
          packages =&gt; $packages,
      }, $class;
  }
  
  sub PRINT {
      my $self = shift;
      my $caller = (caller)[0];
      if ($caller ~~ $self-&gt;{packages}) {
          local *STDOUT = *STDOUT;
          local *STDERR = *STDERR;
          given ($self-&gt;{channel}) {
              when ('stdout') {
                  *STDOUT = $self-&gt;{fh};
              }
              when ('stderr') {
                  *STDERR = $self-&gt;{fh};
              }
          }
          # Capturing/Logging code goes here...
      } else {
          $self-&gt;{fh}-&gt;print(@_);
      }
  }
  
  1;
  
  package main;
  
  use My::Foo;
  # [...]
  use My::Log::Capture;
  open my $stderr, '&gt;&amp;', *STDERR;
  tie *STDERR, 'My::Log::Capture', (stderr =&gt; $stderr, [qw&lt; My::Foo &gt;]);
  # My::Foo's STDERR output will be captured, everyone else's STDERR
  # output will just be relayed.
  </code></pre>