{
    "mode": "perldoc",
    "parameter": "Log::Log4perl::Appender",
    "section": "",
    "url": "https://www.chedong.com/phpMan.php/perldoc/Log%3A%3ALog4perl%3A%3AAppender/json",
    "generated": "2026-06-11T09:44:37Z",
    "synopsis": "use Log::Log4perl;\n# Define a logger\nmy $logger = Log::Log4perl->getlogger(\"abc.def.ghi\");\n# Define a layout\nmy $layout = Log::Log4perl::Layout::PatternLayout->new(\n\"%d (%F:%L)> %m\");\n# Define an appender\nmy $appender = Log::Log4perl::Appender->new(\n\"Log::Log4perl::Appender::Screen\",\nname => 'dumpy');\n# Set the appender's layout\n$appender->layout($layout);\n$logger->addappender($appender);",
    "sections": {
        "NAME": {
            "content": "Log::Log4perl::Appender - Log appender class\n",
            "subsections": []
        },
        "SYNOPSIS": {
            "content": "use Log::Log4perl;\n\n# Define a logger\nmy $logger = Log::Log4perl->getlogger(\"abc.def.ghi\");\n\n# Define a layout\nmy $layout = Log::Log4perl::Layout::PatternLayout->new(\n\"%d (%F:%L)> %m\");\n\n# Define an appender\nmy $appender = Log::Log4perl::Appender->new(\n\"Log::Log4perl::Appender::Screen\",\nname => 'dumpy');\n\n# Set the appender's layout\n$appender->layout($layout);\n$logger->addappender($appender);\n",
            "subsections": []
        },
        "DESCRIPTION": {
            "content": "This class is a wrapper around the \"Log::Log4perl::Appender\" appender set.\n\nIt also supports the <Log::Dispatch::*> collections of appenders. The module hides the\nidiosyncrasies of \"Log::Dispatch\" (e.g. every dispatcher gotta have a name, but there's no\naccessor to retrieve it) from \"Log::Log4perl\" and yet re-uses the extremely useful variety of\ndispatchers already created and tested in \"Log::Dispatch\".\n",
            "subsections": []
        },
        "FUNCTIONS": {
            "content": "Log::Log4perl::Appender->new($dispatcherclassname, ...);\nThe constructor \"new()\" takes the name of the appender class to be created as a *string* (!)\nargument, optionally followed by a number of appender-specific parameters, for example:\n\n# Define an appender\nmy $appender = Log::Log4perl::Appender->new(\n\"Log::Log4perl::Appender::File\"\nfilename => 'out.log');\n\nIn case of \"Log::Dispatch\" appenders, if no \"name\" parameter is specified, the appender object\nwill create a unique one (format \"appNNN\"), which can be retrieved later via the \"name()\"\nmethod:\n\nprint \"The appender's name is \", $appender->name(), \"\\n\";\n\nOther parameters are specific to the appender class being used. In the case above, the\n\"filename\" parameter specifies the name of the \"Log::Log4perl::Appender::File\" dispatcher used.\n\nHowever, if, for instance, you're using a \"Log::Dispatch::Email\" dispatcher to send you email,\nyou'll have to specify \"from\" and \"to\" email addresses. Every dispatcher is different. Please\ncheck the \"Log::Dispatch::*\" documentation for the appender used for details on specific\nrequirements.\n\nThe \"new()\" method will just pass these parameters on to a newly created \"Log::Dispatch::*\"\nobject of the specified type.\n\nWhen it comes to logging, the \"Log::Log4perl::Appender\" will transparently relay all messages to\nthe \"Log::Dispatch::*\" object it carries in its womb.\n\n$appender->layout($layout);\nThe \"layout()\" method sets the log layout used by the appender to the format specified by the\n\"Log::Log4perl::Layout::*\" object which is passed to it as a reference. Currently there's two\nlayouts available:\n\nLog::Log4perl::Layout::SimpleLayout\nLog::Log4perl::Layout::PatternLayout\n\nPlease check the Log::Log4perl::Layout::SimpleLayout and Log::Log4perl::Layout::PatternLayout\nmanual pages for details.\n",
            "subsections": []
        },
        "Supported Appenders": {
            "content": "Here's the list of appender modules currently available via \"Log::Dispatch\", if not noted\notherwise, written by Dave Rolsky:\n\nLog::Dispatch::ApacheLog\nLog::Dispatch::DBI (by Tatsuhiko Miyagawa)\nLog::Dispatch::Email,\nLog::Dispatch::Email::MailSend,\nLog::Dispatch::Email::MailSendmail,\nLog::Dispatch::Email::MIMELite\nLog::Dispatch::File\nLog::Dispatch::FileRotate (by Mark Pfeiffer)\nLog::Dispatch::Handle\nLog::Dispatch::Screen\nLog::Dispatch::Syslog\nLog::Dispatch::Tk (by Dominique Dumont)\n\n\"Log4perl\" doesn't care which ones you use, they're all handled in the same way via the\n\"Log::Log4perl::Appender\" interface. Please check the well-written manual pages of the\n\"Log::Dispatch\" hierarchy on how to use each one of them.\n",
            "subsections": []
        },
        "Parameters passed on to the appender's log() method": {
            "content": "When calling the appender's log()-Funktion, Log::Log4perl will submit a list of key/value pairs.\nEntries to the following keys are guaranteed to be present:\n\nmessage\nText of the rendered message\n\nlog4pcategory\nName of the category of the logger that triggered the event.\n\nlog4plevel\nLog::Log4perl level of the event\n",
            "subsections": []
        },
        "Pitfalls": {
            "content": "Since the \"Log::Dispatch::File\" appender truncates log files by default, and most of the time\nthis is *not* what you want, we've instructed \"Log::Log4perl\" to change this behavior by\nslipping it the \"mode => append\" parameter behind the scenes. So, effectively with\n\"Log::Log4perl\" 0.23, a configuration like\n\nlog4perl.category = INFO, FileAppndr\nlog4perl.appender.FileAppndr          = Log::Dispatch::File\nlog4perl.appender.FileAppndr.filename = test.log\nlog4perl.appender.FileAppndr.layout   = Log::Log4perl::Layout::SimpleLayout\n\nwill always *append* to an existing logfile \"test.log\" while if you specifically request\nclobbering like in\n\nlog4perl.category = INFO, FileAppndr\nlog4perl.appender.FileAppndr          = Log::Dispatch::File\nlog4perl.appender.FileAppndr.filename = test.log\nlog4perl.appender.FileAppndr.mode     = write\nlog4perl.appender.FileAppndr.layout   = Log::Log4perl::Layout::SimpleLayout\n\nit will overwrite an existing log file \"test.log\" and start from scratch.\n",
            "subsections": []
        },
        "Appenders Expecting Message Chunks": {
            "content": "Instead of simple strings, certain appenders are expecting multiple fields as log messages. If a\nstatement like\n\n$logger->debug($ip, $user, \"signed in\");\n\ncauses an off-the-shelf \"Log::Log4perl::Appender::Screen\" appender to fire, the appender will\njust concatenate the three message chunks passed to it in order to form a single string. The\nchunks will be separated by a string defined in $Log::Log4perl::JOINMSGARRAYCHAR (defaults to\nthe empty string \"\").\n\nHowever, different appenders might choose to interpret the message above differently: An\nappender like \"Log::Log4perl::Appender::DBI\" might take the three arguments passed to the logger\nand put them in three separate rows into the DB.\n\nThe \"warpmessage\" appender option is used to specify the desired behavior. If no setting for\nthe appender property\n\n# * Not defined *\n# log4perl.appender.SomeApp.warpmessage\n\nis defined in the Log4perl configuration file, the appender referenced by \"SomeApp\" will fall\nback to the standard behavior and join all message chunks together, separating them by\n$Log::Log4perl::JOINMSGARRAYCHAR.\n\nIf, on the other hand, it is set to a false value, like in\n\nlog4perl.appender.SomeApp.layout=NoopLayout\nlog4perl.appender.SomeApp.warpmessage = 0\n\nthen the message chunks are passed unmodified to the appender as an array reference. Please note\nthat you need to set the appender's layout to \"Log::Log4perl::Layout::NoopLayout\" which just\nleaves the messages chunks alone instead of formatting them or replacing conversion specifiers.\n\nPlease note that the standard appenders in the Log::Dispatch hierarchy will choke on a bunch of\nmessages passed to them as an array reference. You can't use \"warpmessage = 0\" (or the function\nname syntax defined below) on them. Only special appenders like Log::Log4perl::Appender::DBI can\ndeal with this.\n\nIf (and now we're getting fancy) an appender expects message chunks, but we would like to\npre-inspect and probably modify them before they're actually passed to the appender's \"log\"\nmethod, an inspection subroutine can be defined with the appender's \"warpmessage\" property:\n\nlog4perl.appender.SomeApp.layout=NoopLayout\nlog4perl.appender.SomeApp.warpmessage = sub { \\\n$# = 2 if @ > 3; \\\nreturn @; }\n\nThe inspection subroutine defined by the \"warpmessage\" property will receive the list of\nmessage chunks, like they were passed to the logger and is expected to return a corrected list.\nThe example above simply limits the argument list to a maximum of three by cutting off excess\nelements and returning the shortened list.\n\nAlso, the warp function can be specified by name like in\n\nlog4perl.appender.SomeApp.layout=NoopLayout\nlog4perl.appender.SomeApp.warpmessage = main::filtermymessage\n\nIn this example, \"filtermymessage\" is a function in the \"main\" package, defined like this:\n\nmy $COUNTER = 0;\n\nsub filtermymessage {\nmy @chunks = @;\nunshift @chunks, ++$COUNTER;\nreturn @chunks;\n}\n\nThe subroutine above will add an ever increasing counter as an additional first field to every\nmessage passed to the \"SomeApp\" appender -- but not to any other appender in the system.\n",
            "subsections": [
                {
                    "name": "Composite Appenders",
                    "content": "Composite appenders relay their messages to sub-appenders after providing some filtering or\nsynchronizing functionality on incoming messages. Examples are\nLog::Log4perl::Appender::Synchronized, Log::Log4perl::Appender::Limit, and\nLog::Log4perl::Appender::Buffer. Check their manual pages for details.\n\nComposite appender objects are regular Log::Log4perl::Appender objects, but they have the\ncomposite flag set:\n\n$app->composite(1);\n\nand they define a postinit() method, which sets the appender it relays its messages to:\n\n###########################################\nsub postinit {\n############################################\nmy($self) = @;\n\nif(! exists $self->{appender}) {\ndie \"No appender defined for \" . PACKAGE;\n}\n\nmy $appenders = Log::Log4perl->appenders();\nmy $appender = Log::Log4perl->appenders()->{$self->{appender}};\n\nif(! defined $appender) {\ndie \"Appender $self->{appender} not defined (yet) when \" .\nPACKAGE . \" needed it\";\n}\n\n$self->{app} = $appender;\n}\n\nThe reason for this post-processing step is that the relay appender might not be defined yet\nwhen the composite appender gets defined. This can happen if Log4perl is initialized with a\nconfiguration file (which is the most common way to initialize Log4perl), because appenders\nspring into existence in unpredictable order.\n\nFor example, if you define a Synchronized appender like\n\nlog4perl.appender.Syncer            = Log::Log4perl::Appender::Synchronized\nlog4perl.appender.Syncer.appender   = Logfile\n\nthen Log4perl will set the appender's \"appender\" attribute to the *name* of the appender to\nfinally relay messages to. After the Log4perl configuration file has been processed, Log4perl\nwill remember to call the composite appender's postinit() method, which will grab the relay\nappender instance referred to by the name (Logfile) and set it in its \"app\" attribute. This is\nexactly what the code snippet above does.\n\nBut if you initialize Log4perl by its API, you need to remember to perform these steps. Here's\nthe lineup:\n\nuse Log::Log4perl qw(getlogger :levels);\n\nmy $fileApp = Log::Log4perl::Appender->new(\n'Log::Log4perl::Appender::File',\nname     => 'MyFileApp',\nfilename => 'mylog',\nmode     => 'append',\n);\n$fileApp->layout(\nLog::Log4perl::Layout::PatternLayout::Multiline->new(\n'%d{yyyy-MM-dd HH:mm:ss} %p [%c] #%P> %m%n')\n);\n# Make the appender known to the system (without assigning it to\n# any logger\nLog::Log4perl->addappender( $fileApp );\n\nmy $syncApp = Log::Log4perl::Appender->new(\n'Log::Log4perl::Appender::Synchronized',\nname       => 'MySyncApp',\nappender   => 'MyFileApp',\nkey        => 'nem',\n);\n$syncApp->postinit();\n$syncApp->composite(1);\n\n# The Synchronized appender is now ready, assign it to a logger\n# and start logging.\ngetlogger(\"\")->addappender($syncApp);\n\ngetlogger(\"\")->level($DEBUG);\ngetlogger(\"wonk\")->debug(\"waah!\");\n\nThe composite appender's log() function will typically cache incoming messages until a certain\ntrigger condition is met and then forward a bulk of messages to the relay appender.\n\nCaching messages is surprisingly tricky, because you want them to look like they came from the\ncode location they were originally issued from and not from the location that triggers the\nflush. Luckily, Log4perl offers a cache mechanism for messages, all you need to do is call the\nbase class' log() function with an additional reference to a scalar, and then save its content\nto your composite appender's message buffer afterwards:\n\n###########################################\nsub log {\n###########################################\nmy($self, %params) = @;\n\n# ... some logic to decide whether to cache or flush\n\n# Adjust the caller stack\nlocal $Log::Log4perl::callerdepth =\n$Log::Log4perl::callerdepth + 2;\n\n# We need to cache.\n# Ask the appender to save a cached message in $cache\n$self->{relayapp}->SUPER::log(\\%params,\n$params{log4pcategory},\n$params{log4plevel}, \\my $cache);\n\n# Save it in the appender's message buffer\npush @{ $self->{buffer} }, $cache;\n}\n\nNote that before calling the log() method of the relay appender's base class (and thus\nintroducing two additional levels on the call stack), we need to adjust the call stack to allow\nLog4perl to render cspecs like the %M or %L correctly. The cache will then contain a correctly\nrendered message, according to the layout of the target appender.\n\nLater, when the time comes to flush the cached messages, a call to the relay appender's base\nclass' logcached() method with the cached message as an argument will forward the correctly\nrendered message:\n\n###########################################\nsub log {\n###########################################\nmy($self, %params) = @;\n\n# ... some logic to decide whether to cache or flush\n\n# Flush pending messages if we have any\nfor my $cache (@{$self->{buffer}}) {\n$self->{relayapp}->SUPER::logcached($cache);\n}\n}\n"
                }
            ]
        },
        "SEE ALSO": {
            "content": "Log::Dispatch\n",
            "subsections": []
        },
        "LICENSE": {
            "content": "Copyright 2002-2013 by Mike Schilli <m@perlmeister.com> and Kevin Goess <cpan@goess.org>.\n\nThis library is free software; you can redistribute it and/or modify it under the same terms as\nPerl itself.\n",
            "subsections": []
        },
        "AUTHOR": {
            "content": "Please contribute patches to the project on Github:\n\nhttp://github.com/mschilli/log4perl\n\nSend bug reports or requests for enhancements to the authors via our\n\nMAILING LIST (questions, bug reports, suggestions/patches): log4perl-devel@lists.sourceforge.net\n\nAuthors (please contact them via the list above, not directly): Mike Schilli\n<m@perlmeister.com>, Kevin Goess <cpan@goess.org>\n\nContributors (in alphabetical order): Ateeq Altaf, Cory Bennett, Jens Berthold, Jeremy Bopp,\nHutton Davidson, Chris R. Donnelly, Matisse Enzer, Hugh Esco, Anthony Foiani, James FitzGibbon,\nCarl Franks, Dennis Gregorovic, Andy Grundman, Paul Harrington, Alexander Hartmaier David Hull,\nRobert Jacobson, Jason Kohles, Jeff Macdonald, Markus Peter, Brett Rann, Peter Rabbitson, Erik\nSelberg, Aaron Straup Cope, Lars Thegler, David Viner, Mac Yang.\n",
            "subsections": []
        }
    },
    "summary": "Log::Log4perl::Appender - Log appender class",
    "flags": [],
    "examples": [],
    "see_also": []
}