This program is from a Perl Journal article, archived at http://www.stonehenge.com/merlyn/PerlJournal/col09.html.

#!/usr/bin/perl -w
use strict;
$|++;
## CONFIG
my $NICK    = 'weblogger';
my $CONNECT = {
  Server  => 'irc.some.borg',
  Nick    => $NICK,
  Ircname => 'weblogger: see merlyn@stonehenge.com',
};
my $CHANNEL   = '#weblogger';
my $IRC_ALIAS = "irk";
my %FOLLOWS   = (
  ACCESS => "/var/log/access_log",
  ERROR  => "/var/log/error_log",
);
## END CONFIG
my $SKIPPING = 0;    # if skipping, how many we've done
my $SEND_QUEUE;      # cache
use POE qw(Component::IRC Wheel::FollowTail);
POE::Component::IRC->new($IRC_ALIAS);
POE::Session->create(
  inline_states => {
    _start => sub {
      $_[KERNEL]->post($IRC_ALIAS => register => 'all');
      $_[KERNEL]->post($IRC_ALIAS => connect  => $CONNECT);
    },
    irc_255 => sub {    # server is done blabbing
      $_[KERNEL]->post($IRC_ALIAS => join => $CHANNEL);
      $_[KERNEL]->yield("my_heartbeat");    # start heartbeat
      $_[KERNEL]->yield("my_add", $_) for keys %FOLLOWS;
    },
    (
      map {
        ;
        "irc_$_" => sub { }
        } qw(join public
        connected snotice ctcp_action ping notice mode part quit
        001 002 003 004 005
        250 251 252 253 254 265 266
        332 333 353 366 372 375 376)
    ),
    _child   => sub { },
    _default => sub {
      printf "%s: session %s caught an unhandled %s event.\n",
        scalar localtime(), $_[SESSION]->ID, $_[ARG0];
      print "The $_[ARG0] event was given these parameters: ",
        join(" ", map({"ARRAY" eq ref $_ ? "[@$_]" : "$_"} @{$_[ARG1]})),
        "\n";
      0;    # false for signals
    },
    my_add => sub {
      my $trailing = $_[ARG0];
      my $session  = $_[SESSION];
      POE::Session->create(
        inline_states => {
          _start => sub {
            $_[HEAP]->{wheel} = POE::Wheel::FollowTail->new(
              Filename   => $FOLLOWS{$trailing},
              InputEvent => 'got_line',
            );
          },
          got_line => sub {
            $_[KERNEL]->post(
              $session => my_tailed => time,
              $trailing, $_[ARG0]
            );
          },
        },
      );
    },
    my_tailed => sub {
      my ($time, $file, $line) = @_[ARG0 .. ARG2];
      ## $time will be undef on a probe, or a time value if a real line
      ## PoCo::IRC has throttling built in, but no external visibility
      ## so this is reaching "under the hood"
      $SEND_QUEUE ||=
        $_[KERNEL]->alias_resolve($IRC_ALIAS)->get_heap->{send_queue};
      ## handle "no need to keep skipping" transition
      if ($SKIPPING and @$SEND_QUEUE < 1) {
        $_[KERNEL]->post($IRC_ALIAS => privmsg => $CHANNEL =>
            "[discarded $SKIPPING messages]");
        $SKIPPING = 0;
      }
      ## handle potential message display
      if ($time) {
        if ($SKIPPING or @$SEND_QUEUE > 3) {    # 3 msgs per 10 seconds
          $SKIPPING++;
        }
        else {
          my @time = localtime $time;
          $_[KERNEL]->post(
            $IRC_ALIAS => privmsg => $CHANNEL => sprintf
              "%02d:%02d:%02d: %s: %s",
            ($time[2] + 11) % 12 + 1, $time[1], $time[0],
            $file,                    $line
          );
        }
      }
      ## handle re-probe/flush if skipping
      if ($SKIPPING) {
        $_[KERNEL]->delay($_[STATE] => 0.5);    # $time will be undef
      }
    },
    my_heartbeat => sub {
      $_[KERNEL]->yield(my_tailed => time, "heartbeat", "beep");
      $_[KERNEL]->delay($_[STATE] => 10);
      }
  },
);
POE::Kernel->run;