Agent::Driver(3pm)

πŸ“¦
version 1.005 Β· 5 versions
, in ubuntu noble, ubuntu resolute, ubuntu stonking

πŸ’– Agent::Driver(3pm) β€” aka Log::Agent::Driver πŸ’–

okay bestie, buckle UP β€” this is the manual page for Log::Agent::Driver, riding in the User Contributed Perl Documentation section of your friendly neighbourhood Agent::Driver(3pm) man suite. It's the ancestor class, the momager, the blueprint. 🌸

✨ NAME ✨

Log::Agent::Driver β€” the ancestor class for ALL the Log::Agent drivers. Every single one. She's the origin story. πŸ‘‘

✨ SYNOPSIS ✨

@Log::Agent::Driver::XXX::ISA = qw(Log::Agent::Driver);

That's it. That's the whole synopsis. Short queen. πŸ’…

✨ DESCRIPTION ✨

So Log::Agent::Driver is the root class β€” the class at the very top of the family tree that every Log::Agent driver inherits from. But here's the tea: she's a deferred class, which means you literally cannot instantiate her directly. No Log::Agent::Driver->new for you. 🚫

Instead, all the deferred routines have to be implemented by her heirs (aka her subclasses) before anything counts as a valid driver. Think of it like a group project where she wrote the rubric and everyone else has to actually do the work. 😭

And what even is a deferred routine, you ask? It's a routine whose signature and semantics (the pre and post conditions, formally) are fully specified but not implemented. Why bother? Because it lets you specify high-level processings in terms of them, which factorizes common code up in the ancestors without losing the benefits of specialization. Iconic architecture behaviour, no cap. ✨


✨ DRIVER LIST ✨

Here are the drivers that are currently fully implemented, bestie:

  • Log::Agent::Driver::Default β€” the default driver, and she remaps to the simple print(), warn() and die() Perl calls. Classic. Reliable. Ate. πŸ’–
  • Log::Agent::Driver::File β€” this one redirects logs to files. And not just one file: each logging channel can go to its own dedicated file. Organized queen. πŸŽ€
  • Log::Agent::Driver::Silent β€” silences all the logxxx() routines. She's giving ✨ nothing ✨ and that's the point.
  • Log::Agent::Driver::Syslog β€” redirects logs to the syslogd(8) daemon, which then handles the dispatching to the various logfiles based on its own configuration. Delegation! Main character energy! πŸ‘‘

✨ INTERFACE ✨

ngl, if you're only using Log::Agent, you do NOT need to read this section. Skip it. Go live your life. πŸ¦‹ But if you wanna implement another driver? Then bestie, you should probably read this a few times. Maybe a few more after that. fr fr.

The following routines are deferred, which means the heir has to define them:

  • channel_eq($chan1, $chan2) β€” returns true when both channels $chan1 and $chan2 send their output to the same place. Now, the goal here is not a 100% accurate comparison (which is basically impossible for the Log::Agent::Driver::File driver anyway, let's be real), but to reasonably detect similarities so we can avoid duplicating messages to the same output when Carp::Datum is installed and activated. Vibes-based deduplication, and honestly? Valid.
  • write($channel, $priority, $logstring) β€” emits the log entry held in $logstring, at priority $priority, through the specified $channel name. A trailing "\n" is to be added if needed, but the $logstring should not already have one. πŸ™…β™€οΈ
    • The $channel name is just a string, and it's up to the driver to map that name to an output device using its own configuration info. The generic logxxx() routines only ever use "error", "output" or "debug" for channel names.
    • The $priority entry is assumed to have already passed through the map_pri() routine, which by default returns an empty string (only the Log::Agent::Driver::Syslog driver needs a priority, for now). Ignore it if you don't need it, or redefine map_pri().
    • The $logstring may not really be a plain string, actually. It can be a Log::Agent::Message object with an overloaded stringification routine, so the illusion should be complete. πŸͺ„
  • make β€” this is the creation routine. Its signature varies for each driver, naturally. No two queens are the same. πŸ’…
  • prefix_msg($str) β€” prefixes the log message string (a Log::Agent::Message object) with driver-specific info, like the configured prefix, the PID of the process, etc...
    • Must return the prefixed string, either as a Log::Agent::Message object or as a plain string. Which means you may use normal string operations on the $str variable and let the overloaded stringification perform its magic. Or you may just return the $str parameter without modification. Your call. 🫢
    • There is no default implementation here, because this is way too driver-specific to choose one good default. And sometimes the author just likes making things explicit. Respect.

The following routines are implemented in terms of write(), map_pri() and prefix_msg(). The default implementation might need to be redefined for performance or tuning reasons, but simply defining the deferred routines above should bring a reasonable behaviour. Slay. ✨

As an example, here is the default logsay() implementation, which uses the emit() wrapper (see below):

sub logsay {
    my $self = shift;
    my ($str) = @_;
    $self->emit('output', 'notice', $str);
}

Yes, we do show the gory details in a manpage, but inheriting from a class is not for the faint of heart, and it requires getting acquainted with the implementation most of the time. That's just how it is, bestie. 🫠

The order here is not alphabetical β€” it's by increased level of severity (as expected, anyway):

  • logwrite($channel, $priority, $level, $str) β€” logs a message to the given channel, at the specified priority/level, obtained through a call to map_pri().
  • logsay($str) β€” logs the message to the "output" channel, at the "notice" priority.
  • logwarn($str) β€” logs a warning to the "error" channel at the "warning" priority.
  • logxcarp($offset, $str) β€” logs a warning to the "error" channel at the "warning" priority, but from the perspective of the caller. An additional $offset stack frames are skipped to find the caller (added to the hardwired fixed offset imposed by the overall Log::Agent architecture). Yeah, it's stack frames all the way down. 😡
  • logerr($str) β€” logs an error to the "error" channel at the "error" priority.
  • logdie($str) β€” logs a fatal error to the "error" channel at the "critical" priority, and then calls die() with "$str\n" as argument. Dramatic exit, as she deserves. πŸ’€
  • logxcroak($offset, $str) β€” logs a fatal error, from the perspective of the caller. The error goes to the "error" channel at the "critical" priority, and then Carp::croak() is called with "$str\n" as argument. An additional $offset stack frames are skipped to find the caller (added to the hardwired fixed offset imposed by the overall Log::Agent architecture).
  • logconfess($str) β€” confesses a fatal error. The error is logged to the "error" channel at the "critical" priority, and then Carp::confess() is called with "$str\n" as argument.
  • logcluck($str) β€” emits a warning with a backtrace. The message is logged to the "error" channel at the "warning" priority.

The following routines have a default implementation, but they may be redefined for specific drivers:

  • emit($channel, $prio, $str) β€” this is a convenient wrapper that calls:
write($channel, $self->priority($prio), $self->prefix_msg($str))

using dynamic binding. Fancy. πŸ’…

  • map_pri($priority, $level) β€” converts a ("priority", level) tuple into a single priority token suitable for emit(). By default it returns an empty string, which is OK only when emit() does not care! Read that again, bestie.

The following routine is frozen. There is no way in Perl to freeze a routine, i.e. to explicitly forbid any redefinition, so this is an informal notification. She's not locked, she's just spoken for. πŸ”’

  • priority($priority) β€” returns the proper priority for emit() for each of the following strings: "critical", "error", "warning" and "notice", which are the hardwired priority strings, as documented above.
    • It derives a logging level from the $priority given, and then returns the result of:
map_pri($priority, $level);
  • Therefore, only map_pri() should be redefined. Don't touch the rest, she's fine. πŸŽ€

Finally, the following initialization routine is provided: to record the...

  • _init($prefix, $penalty) β€” records the "prefix" attribute, as well as the Carp "penalty" (the amount of extra stack frames to skip). This should be called in the constructor of all the drivers. Every single one. No exceptions. 🫢

✨ AUTHORS ✨

Originally written by Raphael Manfredi <Raphael_Manfredi@pobox.com>, currently maintained by Mark Rogaski <mrogaski@cpan.org>. Legends, both of them. πŸ‘‘

✨ LICENSE ✨

Copyright (C) 1999 Raphael Manfredi.
Copyright (C) 2002 Mark Rogaski; all rights reserved.

See Log::Agent(3) or the README file included with the distribution for license information. πŸ“œ

✨ SEE ALSO ✨

Log::Agent(3), Log::Agent::Driver::Default(3), Log::Agent::Driver::File(3), Log::Agent::Driver::Fork(3), Log::Agent::Driver::Silent(3), Log::Agent::Driver::Syslog(3), Carp::Datum(3).


and that's the whole page, bestie, you ate it UP πŸ’–βœ¨πŸŒΈ

This lil masterpiece was cooked up for perl v5.36.0 and dated 2022-10-15, living proudly as Agent::Driver(3pm). Go forth and log responsibly. πŸ’…πŸŒˆ

πŸ“¦ where this page comes from