{
    "content": [
        {
            "type": "text",
            "text": "# Log::Log4perl::FAQ (perldoc)\n\n## NAME\n\nLog::Log4perl::FAQ - Frequently Asked Questions on Log::Log4perl\n\n## DESCRIPTION\n\nThis FAQ shows a wide variety of commonly encountered logging tasks and how to solve them in the\nmost elegant way with Log::Log4perl. Most of the time, this will be just a matter of smartly\nconfiguring your Log::Log4perl configuration files.\n\n## Sections\n\n- **NAME**\n- **DESCRIPTION**\n- **Figure1: Chainsaw receives Log::Log4perl events**\n- **SEE ALSO**\n- **LICENSE**\n- **AUTHOR**\n\nUse structuredContent.sections for detailed options, examples, and full documentation.\n"
        }
    ],
    "structuredContent": {
        "command": "Log::Log4perl::FAQ",
        "section": "",
        "mode": "perldoc",
        "summary": "Log::Log4perl::FAQ - Frequently Asked Questions on Log::Log4perl",
        "synopsis": null,
        "tldr_summary": null,
        "tldr_examples": [],
        "tldr_source": null,
        "flags": [],
        "examples": [],
        "see_also": [],
        "section_outline": [
            {
                "name": "NAME",
                "lines": 2,
                "subsections": []
            },
            {
                "name": "DESCRIPTION",
                "lines": 1306,
                "subsections": []
            },
            {
                "name": "Figure1: Chainsaw receives Log::Log4perl events",
                "lines": 990,
                "subsections": []
            },
            {
                "name": "SEE ALSO",
                "lines": 2,
                "subsections": []
            },
            {
                "name": "LICENSE",
                "lines": 5,
                "subsections": []
            },
            {
                "name": "AUTHOR",
                "lines": 17,
                "subsections": []
            }
        ],
        "sections": {
            "NAME": {
                "content": "Log::Log4perl::FAQ - Frequently Asked Questions on Log::Log4perl\n",
                "subsections": []
            },
            "DESCRIPTION": {
                "content": "This FAQ shows a wide variety of commonly encountered logging tasks and how to solve them in the\nmost elegant way with Log::Log4perl. Most of the time, this will be just a matter of smartly\nconfiguring your Log::Log4perl configuration files.\n\nWhy use Log::Log4perl instead of any other logging module on CPAN?\nThat's a good question. There's dozens of logging modules on CPAN. When it comes to logging,\npeople typically think: \"Aha. Writing out debug and error messages. Debug is lower than error.\nEasy. I'm gonna write my own.\" Writing a logging module is like a rite of passage for every Perl\nprogrammer, just like writing your own templating system.\n\nOf course, after getting the basics right, features need to be added. You'd like to write a\ntimestamp with every message. Then timestamps with microseconds. Then messages need to be\nwritten to both the screen and a log file.\n\nAnd, as your application grows in size you might wonder: Why doesn't my logging system scale\nalong with it? You would like to switch on logging in selected parts of the application, and not\nall across the board, because this kills performance. This is when people turn to Log::Log4perl,\nbecause it handles all of that.\n\nAvoid this costly switch.\n\nUse \"Log::Log4perl\" right from the start. \"Log::Log4perl\"'s \":easy\" mode supports easy logging\nin simple scripts:\n\nuse Log::Log4perl qw(:easy);\nLog::Log4perl->easyinit($DEBUG);\n\nDEBUG \"A low-level message\";\nERROR \"Won't make it until level gets increased to ERROR\";\n\nAnd when your application inevitably grows, your logging system grows with it without you having\nto change any code.\n\nPlease, don't re-invent logging. \"Log::Log4perl\" is here, it's easy to use, it scales, and\ncovers many areas you haven't thought of yet, but will enter soon.\n\nWhat's the easiest way to use Log4perl?\nIf you just want to get all the comfort of logging, without much overhead, use *Stealth\nLoggers*. If you use Log::Log4perl in \":easy\" mode like\n\nuse Log::Log4perl qw(:easy);\n\nyou'll have the following functions available in the current package:\n\nDEBUG(\"message\");\nINFO(\"message\");\nWARN(\"message\");\nERROR(\"message\");\nFATAL(\"message\");\n\nJust make sure that every package of your code where you're using them in pulls in \"use\nLog::Log4perl qw(:easy)\" first, then you're set. Every stealth logger's category will be\nequivalent to the name of the package it's located in.\n\nThese stealth loggers will be absolutely silent until you initialize Log::Log4perl in your main\nprogram with either\n\n# Define any Log4perl behavior\nLog::Log4perl->init(\"foo.conf\");\n\n(using a full-blown Log4perl config file) or the super-easy method\n\n# Just log to STDERR\nLog::Log4perl->easyinit($DEBUG);\n\nor the parameter-style method with a complexity somewhat in between:\n\n# Append to a log file\nLog::Log4perl->easyinit( { level   => $DEBUG,\nfile    => \">>test.log\" } );\n\nFor more info, please check out \"Stealth Loggers\" in Log::Log4perl.\n\nHow can I simply log all my ERROR messages to a file?\nAfter pulling in the \"Log::Log4perl\" module, just initialize its behavior by passing in a\nconfiguration to its \"init\" method as a string reference. Then, obtain a logger instance and\nwrite out a message with its \"error()\" method:\n\nuse Log::Log4perl qw(getlogger);\n\n# Define configuration\nmy $conf = q(\nlog4perl.logger                    = ERROR, FileApp\nlog4perl.appender.FileApp          = Log::Log4perl::Appender::File\nlog4perl.appender.FileApp.filename = test.log\nlog4perl.appender.FileApp.layout   = PatternLayout\nlog4perl.appender.FileApp.layout.ConversionPattern = %d> %m%n\n);\n\n# Initialize logging behavior\nLog::Log4perl->init( \\$conf );\n\n# Obtain a logger instance\nmy $logger = getlogger(\"Bar::Twix\");\n$logger->error(\"Oh my, a dreadful error!\");\n$logger->warn(\"Oh my, a dreadful warning!\");\n\nThis will append something like\n\n2002/10/29 20:11:55> Oh my, a dreadful error!\n\nto the log file \"test.log\". How does this all work?\n\nWhile the Log::Log4perl \"init()\" method typically takes the name of a configuration file as its\ninput parameter like in\n\nLog::Log4perl->init( \"/path/mylog.conf\" );\n\nthe example above shows how to pass in a configuration as text in a scalar reference.\n\nThe configuration as shown defines a logger of the root category, which has an appender of type\n\"Log::Log4perl::Appender::File\" attached. The line\n\nlog4perl.logger = ERROR, FileApp\n\ndoesn't list a category, defining a root logger. Compare that with\n\nlog4perl.logger.Bar.Twix = ERROR, FileApp\n\nwhich would define a logger for the category \"Bar::Twix\", showing probably different behavior.\n\"FileApp\" on the right side of the assignment is an arbitrarily defined variable name, which is\nonly used to somehow reference an appender defined later on.\n\nAppender settings in the configuration are defined as follows:\n\nlog4perl.appender.FileApp          = Log::Log4perl::Appender::File\nlog4perl.appender.FileApp.filename = test.log\n\nIt selects the file appender of the \"Log::Log4perl::Appender\" hierarchy, which will append to\nthe file \"test.log\" if it already exists. If we wanted to overwrite a potentially existing file,\nwe would have to explicitly set the appropriate \"Log::Log4perl::Appender::File\" parameter\n\"mode\":\n\nlog4perl.appender.FileApp          = Log::Log4perl::Appender::File\nlog4perl.appender.FileApp.filename = test.log\nlog4perl.appender.FileApp.mode     = write\n\nAlso, the configuration defines a PatternLayout format, adding the nicely formatted current date\nand time, an arrow (>) and a space before the messages, which is then followed by a newline:\n\nlog4perl.appender.FileApp.layout   = PatternLayout\nlog4perl.appender.FileApp.layout.ConversionPattern = %d> %m%n\n\nObtaining a logger instance and actually logging something is typically done in a different\nsystem part as the Log::Log4perl initialisation section, but in this example, it's just done\nright after init for the sake of compactness:\n\n# Obtain a logger instance\nmy $logger = getlogger(\"Bar::Twix\");\n$logger->error(\"Oh my, a dreadful error!\");\n\nThis retrieves an instance of the logger of the category \"Bar::Twix\", which, as all other\ncategories, inherits behavior from the root logger if no other loggers are defined in the\ninitialization section.\n\nThe \"error()\" method fires up a message, which the root logger catches. Its priority is equal to\nor higher than the root logger's priority (ERROR), which causes the root logger to forward it to\nits attached appender. By contrast, the following\n\n$logger->warn(\"Oh my, a dreadful warning!\");\n\ndoesn't make it through, because the root logger sports a higher setting (ERROR and up) than the\nWARN priority of the message.\n\nHow can I install Log::Log4perl on Microsoft Windows?\nYou can install Log::Log4perl using the CPAN client.\n\nAlternatively you can install it using\n\nppm install Log-Log4perl\n\nif you're using ActiveState perl.\n\nThat's it! Afterwards, just create a Perl script like\n\nuse Log::Log4perl qw(:easy);\nLog::Log4perl->easyinit($DEBUG);\n\nmy $logger = getlogger(\"Twix::Bar\");\n$logger->debug(\"Watch me!\");\n\nand run it. It should print something like\n\n2002/11/06 01:22:05 Watch me!\n\nIf you find that something doesn't work, please let us know at\nlog4perl-devel@lists.sourceforge.net -- we'll appreciate it. Have fun!\n\nHow can I include global (thread-specific) data in my log messages?\nSay, you're writing a web application and want all your log messages to include the current\nclient's IP address. Most certainly, you don't want to include it in each and every log message\nlike in\n\n$logger->debug( $r->connection->remoteip,\n\" Retrieving user data from DB\" );\n\ndo you? Instead, you want to set it in a global data structure and have Log::Log4perl include it\nautomatically via a PatternLayout setting in the configuration file:\n\nlog4perl.appender.FileApp.layout.ConversionPattern = %X{ip} %m%n\n\nThe conversion specifier %X{ip} references an entry under the key \"ip\" in the global \"MDC\"\n(mapped diagnostic context) table, which you've set once via\n\nLog::Log4perl::MDC->put(\"ip\", $r->connection->remoteip);\n\nat the start of the request handler. Note that this is a *static* (class) method, there's no\nlogger object involved. You can use this method with as many key/value pairs as you like as long\nas you reference them under different names.\n\nThe mappings are stored in a global hash table within Log::Log4perl. Luckily, because the thread\nmodel in 5.8.0 doesn't share global variables between threads unless they're explicitly marked\nas such, there's no problem with multi-threaded environments.\n\nFor more details on the MDC, please refer to \"Mapped Diagnostic Context (MDC)\" in Log::Log4perl\nand Log::Log4perl::MDC.\n\nMy application is already logging to a file. How can I duplicate all messages to also go to the screen?\nAssuming that you already have a Log4perl configuration file like\n\nlog4perl.logger                    = DEBUG, FileApp\n\nlog4perl.appender.FileApp          = Log::Log4perl::Appender::File\nlog4perl.appender.FileApp.filename = test.log\nlog4perl.appender.FileApp.layout   = PatternLayout\nlog4perl.appender.FileApp.layout.ConversionPattern = %d> %m%n\n\nand log statements all over your code, it's very easy with Log4perl to have the same messages\nboth printed to the logfile and the screen. No reason to change your code, of course, just add\nanother appender to the configuration file and you're done:\n\nlog4perl.logger                    = DEBUG, FileApp, ScreenApp\n\nlog4perl.appender.FileApp          = Log::Log4perl::Appender::File\nlog4perl.appender.FileApp.filename = test.log\nlog4perl.appender.FileApp.layout   = PatternLayout\nlog4perl.appender.FileApp.layout.ConversionPattern = %d> %m%n\n\nlog4perl.appender.ScreenApp          = Log::Log4perl::Appender::Screen\nlog4perl.appender.ScreenApp.stderr   = 0\nlog4perl.appender.ScreenApp.layout   = PatternLayout\nlog4perl.appender.ScreenApp.layout.ConversionPattern = %d> %m%n\n\nThe configuration file above is assuming that both appenders are active in the same logger\nhierarchy, in this case the \"root\" category. But even if you've got file loggers defined in\nseveral parts of your system, belonging to different logger categories, each logging to\ndifferent files, you can gobble up all logged messages by defining a root logger with a screen\nappender, which would duplicate messages from all your file loggers to the screen due to\nLog4perl's appender inheritance. Check\n\nhttp://www.perl.com/pub/a/2002/09/11/log4perl.html\n\nfor details. Have fun!\n\nHow can I make sure my application logs a message when it dies unexpectedly?\nWhenever you encounter a fatal error in your application, instead of saying something like\n\nopen FILE, \"<blah\" or die \"Can't open blah -- bailing out!\";\n\njust use Log::Log4perl's fatal functions instead:\n\nmy $log = getlogger(\"Some::Package\");\nopen FILE, \"<blah\" or $log->logdie(\"Can't open blah -- bailing out!\");\n\nThis will both log the message with priority FATAL according to your current Log::Log4perl\nconfiguration and then call Perl's \"die()\" afterwards to terminate the program. It works the\nsame with stealth loggers (see \"Stealth Loggers\" in Log::Log4perl), all you need to do is call\n\nuse Log::Log4perl qw(:easy);\nopen FILE, \"<blah\" or LOGDIE \"Can't open blah -- bailing out!\";\n\nWhat can you do if you're using some library which doesn't use Log::Log4perl and calls \"die()\"\ninternally if something goes wrong? Use a $SIG{DIE} pseudo signal handler\n\nuse Log::Log4perl qw(getlogger);\n\n$SIG{DIE} = sub {\nif($^S) {\n# We're in an eval {} and don't want log\n# this message but catch it later\nreturn;\n}\nlocal $Log::Log4perl::callerdepth =\n$Log::Log4perl::callerdepth + 1;\nmy $logger = getlogger(\"\");\n$logger->fatal(@);\ndie @; # Now terminate really\n};\n\nThis will catch every \"die()\"-Exception of your application or the modules it uses. In case you\nwant to It will fetch a root logger and pass on the \"die()\"-Message to it. If you make sure\nyou've configured with a root logger like this:\n\nLog::Log4perl->init(\\q{\nlog4perl.category         = FATAL, Logfile\nlog4perl.appender.Logfile = Log::Log4perl::Appender::File\nlog4perl.appender.Logfile.filename = fatalerrors.log\nlog4perl.appender.Logfile.layout = \\\nLog::Log4perl::Layout::PatternLayout\nlog4perl.appender.Logfile.layout.ConversionPattern = %F{1}-%L (%M)> %m%n\n});\n\nthen all \"die()\" messages will be routed to a file properly. The line\n\nlocal $Log::Log4perl::callerdepth =\n$Log::Log4perl::callerdepth + 1;\n\nin the pseudo signal handler above merits a more detailed explanation. With the setup above, if\na module calls \"die()\" in one of its functions, the fatal message will be logged in the signal\nhandler and not in the original function -- which will cause the %F, %L and %M placeholders in\nthe pattern layout to be replaced by the filename, the line number and the function/method name\nof the signal handler, not the error-throwing module. To adjust this, Log::Log4perl has the\n$callerdepth variable, which defaults to 0, but can be set to positive integer values to offset\nthe caller level. Increasing it by one will cause it to log the calling function's parameters,\nnot the ones of the signal handler. See \"Using Log::Log4perl from wrapper classes\" in\nLog::Log4perl for more details.\n\nHow can I hook up the LWP library with Log::Log4perl?\nOr, to put it more generally: How can you utilize a third-party library's embedded logging and\ndebug statements in Log::Log4perl? How can you make them print to configurable appenders, turn\nthem on and off, just as if they were regular Log::Log4perl logging statements?\n\nThe easiest solution is to map the third-party library logging statements to Log::Log4perl's\nstealth loggers via a typeglob assignment.\n\nAs an example, let's take LWP, one of the most popular Perl modules, which makes handling WWW\nrequests and responses a breeze. Internally, LWP uses its own logging and debugging system,\nutilizing the following calls inside the LWP code (from the LWP::Debug man page):\n\n# Function tracing\nLWP::Debug::trace('send()');\n\n# High-granular state in functions\nLWP::Debug::debug('url ok');\n\n# Data going over the wire\nLWP::Debug::conns(\"read $n bytes: $data\");\n\nFirst, let's assign Log::Log4perl priorities to these functions: I'd suggest that \"debug()\"\nmessages have priority \"INFO\", \"trace()\" uses \"DEBUG\" and \"conns()\" also logs with \"DEBUG\" --\nalthough your mileage may certainly vary.\n\nNow, in order to transparently hook up LWP::Debug with Log::Log4perl, all we have to do is say\n\npackage LWP::Debug;\nuse Log::Log4perl qw(:easy);\n\n*trace = *INFO;\n*conns = *DEBUG;\n*debug = *DEBUG;\n\npackage main;\n# ... go on with your regular program ...\n\nat the beginning of our program. In this way, every time the, say, \"LWP::UserAgent\" module calls\n\"LWP::Debug::trace()\", it will implicitly call INFO(), which is the \"info()\" method of a stealth\nlogger defined for the Log::Log4perl category \"LWP::Debug\". Is this cool or what?\n\nHere's a complete program:\n\nuse LWP::UserAgent;\nuse HTTP::Request::Common;\nuse Log::Log4perl qw(:easy);\n\nLog::Log4perl->easyinit(\n{ category => \"LWP::Debug\",\nlevel    => $DEBUG,\nlayout   => \"%r %p %M-%L %m%n\",\n});\n\npackage LWP::Debug;\nuse Log::Log4perl qw(:easy);\n*trace = *INFO;\n*conns = *DEBUG;\n*debug = *DEBUG;\n\npackage main;\nmy $ua = LWP::UserAgent->new();\nmy $resp = $ua->request(GET \"http://amazon.com\");\n\nif($resp->issuccess()) {\nprint \"Success: Received \",\nlength($resp->content()), \"\\n\";\n} else {\nprint \"Error: \", $resp->code(), \"\\n\";\n}\n\nThis will generate the following output on STDERR:\n\n174 INFO LWP::UserAgent::new-164 ()\n208 INFO LWP::UserAgent::request-436 ()\n211 INFO LWP::UserAgent::sendrequest-294 GET http://amazon.com\n212 DEBUG LWP::UserAgent::needproxy-1123 Not proxied\n405 INFO LWP::Protocol::http::request-122 ()\n859 DEBUG LWP::Protocol::collect-206 read 233 bytes\n863 DEBUG LWP::UserAgent::request-443 Simple response: Found\n869 INFO LWP::UserAgent::request-436 ()\n871 INFO LWP::UserAgent::sendrequest-294\nGET http://www.amazon.com:80/exec/obidos/gatewayredirect\n872 DEBUG LWP::UserAgent::needproxy-1123 Not proxied\n873 INFO LWP::Protocol::http::request-122 ()\n1016 DEBUG LWP::UserAgent::request-443 Simple response: Found\n1020 INFO LWP::UserAgent::request-436 ()\n1022 INFO LWP::UserAgent::sendrequest-294\nGET http://www.amazon.com/exec/obidos/subst/home/home.html/\n1023 DEBUG LWP::UserAgent::needproxy-1123 Not proxied\n1024 INFO LWP::Protocol::http::request-122 ()\n1382 DEBUG LWP::Protocol::collect-206 read 632 bytes\n...\n2605 DEBUG LWP::Protocol::collect-206 read 77 bytes\n2607 DEBUG LWP::UserAgent::request-443 Simple response: OK\nSuccess: Received 42584\n\nOf course, in this way, the embedded logging and debug statements within LWP can be utilized in\nany Log::Log4perl way you can think of. You can have them sent to different appenders, block\nthem based on the category and everything else Log::Log4perl has to offer.\n\nOnly drawback of this method: Steering logging behavior via category is always based on the\n\"LWP::Debug\" package. Although the logging statements reflect the package name of the issuing\nmodule properly, the stealth loggers in \"LWP::Debug\" are all of the category \"LWP::Debug\". This\nimplies that you can't control the logging behavior based on the package that's *initiating* a\nlog request (e.g. LWP::UserAgent) but only based on the package that's actually *executing* the\nlogging statement, \"LWP::Debug\" in this case.\n\nTo work around this conundrum, we need to write a wrapper function and plant it into the\n\"LWP::Debug\" package. It will determine the caller and create a logger bound to a category with\nthe same name as the caller's package:\n\npackage LWP::Debug;\n\nuse Log::Log4perl qw(:levels getlogger);\n\nsub l4pwrapper {\nmy($prio, @message) = @;\n$Log::Log4perl::callerdepth += 2;\ngetlogger(scalar caller(1))->log($prio, @message);\n$Log::Log4perl::callerdepth -= 2;\n}\n\nno warnings 'redefine';\n*trace = sub { l4pwrapper($INFO, @); };\n*debug = *conns = sub { l4pwrapper($DEBUG, @); };\n\npackage main;\n# ... go on with your main program ...\n\nThis is less performant than the previous approach, because every log request will request a\nreference to a logger first, then call the wrapper, which will in turn call the appropriate log\nfunction.\n\nThis hierarchy shift has to be compensated for by increasing $Log::Log4perl::callerdepth by 2\nbefore calling the log function and decreasing it by 2 right afterwards. Also, the \"l4pwrapper\"\nfunction shown above calls caller(1) which determines the name of the package *two* levels down\nthe calling hierarchy (and therefore compensates for both the wrapper function and the anonymous\nsubroutine calling it).\n\n\"no warnings 'redefine'\" suppresses a warning Perl would generate otherwise upon redefining\n\"LWP::Debug\"'s \"trace()\", \"debug()\" and \"conns()\" functions. In case you use a perl prior to\n5.6.x, you need to manipulate $^W instead.\n\nTo make things easy for you when dealing with LWP, Log::Log4perl 0.47 introduces\n\"Log::Log4perl->infiltratelwp()\" which does exactly the above.\n\nWhat if I need dynamic values in a static Log4perl configuration file?\nSay, your application uses Log::Log4perl for logging and therefore comes with a Log4perl\nconfiguration file, specifying the logging behavior. But, you also want it to take command line\nparameters to set values like the name of the log file. How can you have both a static Log4perl\nconfiguration file and a dynamic command line interface?\n\nAs of Log::Log4perl 0.28, every value in the configuration file can be specified as a *Perl\nhook*. So, instead of saying\n\nlog4perl.appender.Logfile.filename = test.log\n\nyou could just as well have a Perl subroutine deliver the value dynamically:\n\nlog4perl.appender.Logfile.filename = sub { logfile(); };\n\ngiven that \"logfile()\" is a valid function in your \"main\" package returning a string containing\nthe path to the log file.\n\nOr, think about using the value of an environment variable:\n\nlog4perl.appender.DBI.user = sub { $ENV{USERNAME} };\n\nWhen \"Log::Log4perl->init()\" parses the configuration file, it will notice the assignment above\nbecause of its \"sub {...}\" pattern and treat it in a special way: It will evaluate the\nsubroutine (which can contain arbitrary Perl code) and take its return value as the right side\nof the assignment.\n\nA typical application would be called like this on the command line:\n\napp                # log file is \"test.log\"\napp -l mylog.txt   # log file is \"mylog.txt\"\n\nHere's some sample code implementing the command line interface above:\n\nuse Log::Log4perl qw(getlogger);\nuse Getopt::Std;\n\ngetopt('l:', \\our %OPTS);\n\nmy $conf = q(\nlog4perl.category.Bar.Twix         = WARN, Logfile\nlog4perl.appender.Logfile          = Log::Log4perl::Appender::File\nlog4perl.appender.Logfile.filename = sub { logfile(); };\nlog4perl.appender.Logfile.layout   = SimpleLayout\n);\n\nLog::Log4perl::init(\\$conf);\n\nmy $logger = getlogger(\"Bar::Twix\");\n$logger->error(\"Blah\");\n\n###########################################\nsub logfile {\n###########################################\nif(exists $OPTS{l}) {\nreturn $OPTS{l};\n} else {\nreturn \"test.log\";\n}\n}\n\nEvery Perl hook may contain arbitrary perl code, just make sure to fully qualify eventual\nvariable names (e.g. %main::OPTS instead of %OPTS).\n\nSECURITY NOTE: this feature means arbitrary perl code can be embedded in the config file. In the\nrare case where the people who have access to your config file are different from the people who\nwrite your code and shouldn't have execute rights, you might want to call\n\n$Log::Log4perl::Config->allowcode(0);\n\nbefore you call init(). This will prevent Log::Log4perl from executing *any* Perl code in the\nconfig file (including code for custom conversion specifiers (see \"Custom cspecs\" in\nLog::Log4perl::Layout::PatternLayout).\n\nHow can I roll over my logfiles automatically at midnight?\nLong-running applications tend to produce ever-increasing logfiles. For backup and cleanup\npurposes, however, it is often desirable to move the current logfile to a different location\nfrom time to time and start writing a new one.\n\nThis is a non-trivial task, because it has to happen in sync with the logging system in order\nnot to lose any messages in the process.\n\nLuckily, *Mark Pfeiffer*'s \"Log::Dispatch::FileRotate\" appender works well with Log::Log4perl to\nrotate your logfiles in a variety of ways.\n\nNote, however, that having the application deal with rotating a log file is not cheap. Among\nother things, it requires locking the log file with every write to avoid race conditions. There\nare good reasons to use external rotators like \"newsyslog\" instead. See the entry \"How can I\nrotate a logfile with newsyslog?\" in the FAQ for more information on how to configure it.\n\nWhen using \"Log::Dispatch::FileRotate\", all you have to do is specify it in your Log::Log4perl\nconfiguration file and your logfiles will be rotated automatically.\n\nYou can choose between rolling based on a maximum size (\"roll if greater than 10 MB\") or based\non a date pattern (\"roll everyday at midnight\"). In both cases, \"Log::Dispatch::FileRotate\"\nallows you to define a number \"max\" of saved files to keep around until it starts overwriting\nthe oldest ones. If you set the \"max\" parameter to 2 and the name of your logfile is \"test.log\",\n\"Log::Dispatch::FileRotate\" will move \"test.log\" to \"test.log.1\" on the first rollover. On the\nsecond rollover, it will move \"test.log.1\" to \"test.log.2\" and then \"test.log\" to \"test.log.1\".\nOn the third rollover, it will move \"test.log.1\" to \"test.log.2\" (therefore discarding the old\n\"test.log.2\") and \"test.log\" to \"test.log.1\". And so forth. This way, there's always going to be\na maximum of 2 saved log files around.\n\nHere's an example of a Log::Log4perl configuration file, defining a daily rollover at midnight\n(date pattern \"yyyy-MM-dd\"), keeping a maximum of 5 saved logfiles around:\n\nlog4perl.category         = WARN, Logfile\nlog4perl.appender.Logfile = Log::Dispatch::FileRotate\nlog4perl.appender.Logfile.filename    = test.log\nlog4perl.appender.Logfile.max         = 5\nlog4perl.appender.Logfile.DatePattern = yyyy-MM-dd\nlog4perl.appender.Logfile.TZ          = PST\nlog4perl.appender.Logfile.layout = \\\nLog::Log4perl::Layout::PatternLayout\nlog4perl.appender.Logfile.layout.ConversionPattern = %d %m %n\n\nPlease see the \"Log::Dispatch::FileRotate\" documentation for details.\n\"Log::Dispatch::FileRotate\" is available on CPAN.\n\nWhat's the easiest way to turn off all logging, even with a lengthy Log4perl configuration file?\nIn addition to category-based levels and appender thresholds, Log::Log4perl supports system-wide\nlogging thresholds. This is the minimum level the system will require of any logging events in\norder for them to make it through to any configured appenders.\n\nFor example, putting the line\n\nlog4perl.threshold = ERROR\n\nanywhere in your configuration file will limit any output to any appender to events with\npriority of ERROR or higher (ERROR or FATAL that is).\n\nHowever, in order to suppress all logging entirely, you need to use a priority that's higher\nthan FATAL: It is simply called \"OFF\", and it is never used by any logger. By definition, it is\nhigher than the highest defined logger level.\n\nTherefore, if you keep the line\n\nlog4perl.threshold = OFF\n\nsomewhere in your Log::Log4perl configuration, the system will be quiet as a graveyard. If you\ndeactivate the line (e.g. by commenting it out), the system will, upon config reload, snap back\nto normal operation, providing logging messages according to the rest of the configuration file\nagain.\n\nHow can I log DEBUG and above to the screen and INFO and above to a file?\nYou need one logger with two appenders attached to it:\n\nlog4perl.logger = DEBUG, Screen, File\n\nlog4perl.appender.Screen   = Log::Log4perl::Appender::Screen\nlog4perl.appender.Screen.layout = SimpleLayout\n\nlog4perl.appender.File   = Log::Log4perl::Appender::File\nlog4perl.appender.File.filename = test.log\nlog4perl.appender.File.layout = SimpleLayout\nlog4perl.appender.Screen.Threshold = INFO\n\nSince the file logger isn't supposed to get any messages with a priority less than INFO, the\nappender's \"Threshold\" setting blocks those out, although the logger forwards them.\n\nIt's a common mistake to think you can define two loggers for this, but it won't work unless\nthose two loggers have different categories. If you wanted to log all DEBUG and above messages\nfrom the Foo::Bar module to a file and all INFO and above messages from the Quack::Schmack\nmodule to the screen, then you could have defined two loggers with different levels\n\"log4perl.logger.Foo.Bar\" (level INFO) and \"log4perl.logger.Quack.Schmack\" (level DEBUG) and\nassigned the file appender to the former and the screen appender to the latter. But what we\nwanted to accomplish was to route all messages, regardless of which module (or category) they\ncame from, to both appenders. The only way to accomplish this is to define the root logger with\nthe lower level (DEBUG), assign both appenders to it, and block unwanted messages at the file\nappender (\"Threshold\" set to INFO).\n\nI keep getting duplicate log messages! What's wrong?\nHaving several settings for related categories in the Log4perl configuration file sometimes\nleads to a phenomenon called \"message duplication\". It can be very confusing at first, but if\nthought through properly, it turns out that Log4perl behaves as advertised. But, don't despair,\nof course there's a number of ways to avoid message duplication in your logs.\n\nHere's a sample Log4perl configuration file that produces the phenomenon:\n\nlog4perl.logger.Cat        = ERROR, Screen\nlog4perl.logger.Cat.Subcat = WARN, Screen\n\nlog4perl.appender.Screen   = Log::Log4perl::Appender::Screen\nlog4perl.appender.Screen.layout = SimpleLayout\n\nIt defines two loggers, one for category \"Cat\" and one for \"Cat::Subcat\", which is obviously a\nsubcategory of \"Cat\". The parent logger has a priority setting of ERROR, the child is set to the\nlower \"WARN\" level.\n\nNow imagine the following code in your program:\n\nmy $logger = getlogger(\"Cat.Subcat\");\n$logger->warn(\"Warning!\");\n\nWhat do you think will happen? An unexperienced Log4perl user might think: \"Well, the message is\nbeing sent with level WARN, so the \"Cat::Subcat\" logger will accept it and forward it to the\nattached \"Screen\" appender. Then, the message will percolate up the logger hierarchy, find the\n\"Cat\" logger, which will suppress the message because of its ERROR setting.\" But, perhaps\nsurprisingly, what you'll get with the code snippet above is not one but two log messages\nwritten to the screen:\n\nWARN - Warning!\nWARN - Warning!\n\nWhat happened? The culprit is that once the logger \"Cat::Subcat\" decides to fire, it will\nforward the message *unconditionally* to all directly or indirectly attached appenders. The\n\"Cat\" logger will never be asked if it wants the message or not -- the message will just be\npushed through to the appender attached to \"Cat\".\n\nOne way to prevent the message from bubbling up the logger hierarchy is to set the \"additivity\"\nflag of the subordinate logger to 0:\n\nlog4perl.logger.Cat            = ERROR, Screen\nlog4perl.logger.Cat.Subcat     = WARN, Screen\nlog4perl.additivity.Cat.Subcat = 0\n\nlog4perl.appender.Screen   = Log::Log4perl::Appender::Screen\nlog4perl.appender.Screen.layout = SimpleLayout\n\nThe message will now be accepted by the \"Cat::Subcat\" logger, forwarded to its appender, but\nthen \"Cat::Subcat\" will suppress any further action. While this setting avoids duplicate\nmessages as seen before, it is often not the desired behavior. Messages percolating up the\nhierarchy are a useful Log4perl feature.\n\nIf you're defining *different* appenders for the two loggers, one other option is to define an\nappender threshold for the higher-level appender. Typically it is set to be equal to the\nlogger's level setting:\n\nlog4perl.logger.Cat           = ERROR, Screen1\nlog4perl.logger.Cat.Subcat    = WARN, Screen2\n\nlog4perl.appender.Screen1   = Log::Log4perl::Appender::Screen\nlog4perl.appender.Screen1.layout = SimpleLayout\nlog4perl.appender.Screen1.Threshold = ERROR\n\nlog4perl.appender.Screen2   = Log::Log4perl::Appender::Screen\nlog4perl.appender.Screen2.layout = SimpleLayout\n\nSince the \"Screen1\" appender now blocks every message with a priority less than ERROR, even if\nthe logger in charge lets it through, the message percolating up the hierarchy is being blocked\nat the last minute and *not* appended to \"Screen1\".\n\nSo far, we've been operating well within the boundaries of the Log4j standard, which Log4perl\nadheres to. However, if you would really, really like to use a single appender and keep the\nmessage percolation intact without having to deal with message duplication, there's a\nnon-standard solution for you:\n\nlog4perl.logger.Cat        = ERROR, Screen\nlog4perl.logger.Cat.Subcat = WARN, Screen\n\nlog4perl.appender.Screen   = Log::Log4perl::Appender::Screen\nlog4perl.appender.Screen.layout = SimpleLayout\n\nlog4perl.oneMessagePerAppender = 1\n\nThe \"oneMessagePerAppender\" flag will suppress duplicate messages to the same appender. Again,\nthat's non-standard. But way cool :).\n\nHow can I configure Log::Log4perl to send me email if something happens?\nSome incidents require immediate action. You can't wait until someone checks the log files, you\nneed to get notified on your pager right away.\n\nThe easiest way to do that is by using the \"Log::Dispatch::Email::MailSend\" module as an\nappender. It comes with the \"Log::Dispatch\" bundle and allows you to specify recipient and\nsubject of outgoing emails in the Log4perl configuration file:\n\nlog4perl.category = FATAL, Mailer\nlog4perl.appender.Mailer         = Log::Dispatch::Email::MailSend\nlog4perl.appender.Mailer.to      = drone@pageme.net\nlog4perl.appender.Mailer.subject = Something's broken!\nlog4perl.appender.Mailer.layout  = SimpleLayout\n\nThe message of every log incident this appender gets will then be forwarded to the given email\naddress. Check the \"Log::Dispatch::Email::MailSend\" documentation for details. And please make\nsure there's not a flood of email messages sent out by your application, filling up the\nrecipient's inbox.\n\nThere's one caveat you need to know about: The \"Log::Dispatch::Email\" hierarchy of appenders\nturns on *buffering* by default. This means that the appender will not send out messages right\naway but wait until a certain threshold has been reached. If you'd rather have your alerts sent\nout immediately, use\n\nlog4perl.appender.Mailer.buffered = 0\n\nto turn buffering off.\n\nHow can I write my own appender?\nFirst off, Log::Log4perl comes with a set of standard appenders. Then, there's a lot of\nLog4perl-compatible appenders already available on CPAN: Just run a search for \"Log::Dispatch\"\non http://search.cpan.org and chances are that what you're looking for has already been\ndeveloped, debugged and been used successfully in production -- no need for you to reinvent the\nwheel.\n\nAlso, Log::Log4perl ships with a nifty database appender named Log::Log4perl::Appender::DBI --\ncheck it out if talking to databases is your desire.\n\nBut if you're up for a truly exotic task, you might have to write an appender yourself. That's\nvery easy -- it takes no longer than a couple of minutes.\n\nSay, we wanted to create an appender of the class \"ColorScreenAppender\", which logs messages to\nthe screen in a configurable color. Just create a new class in \"ColorScreenAppender.pm\":\n\npackage ColorScreenAppender;\n\nNow let's assume that your Log::Log4perl configuration file \"test.conf\" looks like this:\n\nlog4perl.logger = INFO, ColorApp\n\nlog4perl.appender.ColorApp=ColorScreenAppender\nlog4perl.appender.ColorApp.color=blue\n\nlog4perl.appender.ColorApp.layout = PatternLayout\nlog4perl.appender.ColorApp.layout.ConversionPattern=%d %m %n\n\nThis will cause Log::Log4perl on \"init()\" to look for a class ColorScreenAppender and call its\nconstructor new(). Let's add new() to ColorScreenAppender.pm:\n\nsub new {\nmy($class, %options) = @;\n\nmy $self = { %options };\nbless $self, $class;\n\nreturn $self;\n}\n\nTo initialize this appender, Log::Log4perl will call and pass all attributes of the appender as\ndefined in the configuration file to the constructor as name/value pairs (in this case just\none):\n\nColorScreenAppender->new(color => \"blue\");\n\nThe new() method listed above stores the contents of the %options hash in the object's instance\ndata hash (referred to by $self). That's all for initializing a new appender with Log::Log4perl.\n\nSecond, ColorScreenAppender needs to expose a \"log()\" method, which will be called by\nLog::Log4perl every time it thinks the appender should fire. Along with the object reference (as\nusual in Perl's object world), log() will receive a list of name/value pairs, of which only the\none under the key \"message\" shall be of interest for now since it is the message string to be\nlogged. At this point, Log::Log4perl has already taken care of joining the message to be a\nsingle string.\n\nFor our special appender ColorScreenAppender, we're using the Term::ANSIColor module to colorize\nthe output:\n\nuse Term::ANSIColor;\n\nsub log {\nmy($self, %params) = @;\n\nprint colored($params{message},\n$self->{color});\n}\n\nThe color (as configured in the Log::Log4perl configuration file) is available as $self->{color}\nin the appender object. Don't forget to return\n\n1;\n\nat the end of ColorScreenAppender.pm and you're done. Install the new appender somewhere where\nperl can find it and try it with a test script like\n\nuse Log::Log4perl qw(:easy);\nLog::Log4perl->init(\"test.conf\");\nERROR(\"blah\");\n\nto see the new colored output. Is this cool or what?\n\nAnd it gets even better: You can write dynamically generated appender classes using the\n\"Class::Prototyped\" module. Here's an example of an appender prepending every outgoing message\nwith a configurable number of bullets:\n\nuse Class::Prototyped;\n\nmy $class = Class::Prototyped->newPackage(\n\"MyAppenders::Bulletizer\",\nbullets => 1,\nlog     => sub {\nmy($self, %params) = @;\nprint \"*\" x $self->bullets(),\n$params{message};\n},\n);\n\nuse Log::Log4perl qw(:easy);\n\nLog::Log4perl->init(\\ q{\nlog4perl.logger = INFO, Bully\n\nlog4perl.appender.Bully=MyAppenders::Bulletizer\nlog4perl.appender.Bully.bullets=3\n\nlog4perl.appender.Bully.layout = PatternLayout\nlog4perl.appender.Bully.layout.ConversionPattern=%m %n\n});\n\n# ... prints: \"*Boo!\\n\";\nINFO \"Boo!\";\n\nHow can I drill down on references before logging them?\nIf you've got a reference to a nested structure or object, then you probably don't want to log\nit as \"HASH(0x81141d4)\" but rather dump it as something like\n\n$VAR1 = {\n'a' => 'b',\n'd' => 'e'\n};\n\nvia a module like Data::Dumper. While it's syntactically correct to say\n\n$logger->debug(Data::Dumper::Dumper($ref));\n\nthis call imposes a huge performance penalty on your application if the message is suppressed by\nLog::Log4perl, because Data::Dumper will perform its expensive operations in any case, because\nit doesn't know that its output will be thrown away immediately.\n\nAs of Log::Log4perl 0.28, there's a better way: Use the message output filter format as in\n\n$logger->debug( {filter => \\&Data::Dumper::Dumper,\nvalue  => $ref} );\n\nand Log::Log4perl won't call the filter function unless the message really gets written out to\nan appender. Just make sure to pass the whole slew as a reference to a hash specifying a filter\nfunction (as a sub reference) under the key \"filter\" and the value to be passed to the filter\nfunction in \"value\"). When it comes to logging, Log::Log4perl will call the filter function,\npass the \"value\" as an argument and log the return value. Saves you serious cycles.\n\nHow can I collect all FATAL messages in an extra log file?\nSuppose you have employed Log4perl all over your system and you've already activated logging in\nvarious subsystems. On top of that, without disrupting any other settings, how can you collect\nall FATAL messages all over the system and send them to a separate log file?\n\nIf you define a root logger like this:\n\nlog4perl.logger                  = FATAL, File\nlog4perl.appender.File           = Log::Log4perl::Appender::File\nlog4perl.appender.File.filename  = /tmp/fatal.txt\nlog4perl.appender.File.layout    = PatternLayout\nlog4perl.appender.File.layout.ConversionPattern= %d %m %n\n# !!! Something's missing ...\n\nyou'll be surprised to not only receive all FATAL messages issued anywhere in the system, but\nalso everything else -- gazillions of ERROR, WARN, INFO and even DEBUG messages will end up in\nyour fatal.txt logfile! Reason for this is Log4perl's (or better: Log4j's) appender additivity.\nOnce a lower-level logger decides to fire, the message is going to be forwarded to all appenders\nupstream -- without further priority checks with their attached loggers.\n\nThere's a way to prevent this, however: If your appender defines a minimum threshold, only\nmessages of this priority or higher are going to be logged. So, just add\n\nlog4perl.appender.File.Threshold = FATAL\n\nto the configuration above, and you'll get what you wanted in the first place: An overall system\nFATAL message collector.\n\nHow can I bundle several log messages into one?\nWould you like to tally the messages arriving at your appender and dump out a summary once\nthey're exceeding a certain threshold? So that something like\n\n$logger->error(\"Blah\");\n$logger->error(\"Blah\");\n$logger->error(\"Blah\");\n\nwon't be logged as\n\nBlah\nBlah\nBlah\n\nbut as\n\n[3] Blah\n\ninstead? If you'd like to hold off on logging a message until it has been sent a couple of\ntimes, you can roll that out by creating a buffered appender.\n\nLet's define a new appender like\n\npackage TallyAppender;\n\nsub new {\nmy($class, %options) = @;\n\nmy $self = { maxcount => 5,\n%options\n};\n\nbless $self, $class;\n\n$self->{lastmessage}        = \"\";\n$self->{lastmessagecount}  = 0;\n\nreturn $self;\n}\n\nwith two additional instance variables \"lastmessage\" and \"lastmessagecount\", storing the\ncontent of the last message sent and a counter of how many times this has happened. Also, it\nfeatures a configuration parameter \"maxcount\" which defaults to 5 in the snippet above but can\nbe set in the Log4perl configuration file like this:\n\nlog4perl.logger = INFO, A\nlog4perl.appender.A=TallyAppender\nlog4perl.appender.A.maxcount = 3\n\nThe main tallying logic lies in the appender's \"log\" method, which is called every time Log4perl\nthinks a message needs to get logged by our appender:\n\nsub log {\nmy($self, %params) = @;\n\n# Message changed? Print buffer.\nif($self->{lastmessage} and\n$params{message} ne $self->{lastmessage}) {\nprint \"[$self->{lastmessagecount}]: \" .\n\"$self->{lastmessage}\";\n$self->{lastmessagecount} = 1;\n$self->{lastmessage} = $params{message};\nreturn;\n}\n\n$self->{lastmessagecount}++;\n$self->{lastmessage} = $params{message};\n\n# Threshold exceeded? Print, reset counter\nif($self->{lastmessagecount} >=\n$self->{maxcount}) {\nprint \"[$self->{lastmessagecount}]: \" .\n\"$params{message}\";\n$self->{lastmessagecount} = 0;\n$self->{lastmessage}       = \"\";\nreturn;\n}\n}\n\nWe basically just check if the oncoming message in $param{message} is equal to what we've saved\nbefore in the \"lastmessage\" instance variable. If so, we're increasing \"lastmessagecount\". We\nprint the message in two cases: If the new message is different than the buffered one, because\nthen we need to dump the old stuff and store the new. Or, if the counter exceeds the threshold,\nas defined by the \"maxcount\" configuration parameter.\n\nPlease note that the appender always gets the fully rendered message and just compares it as a\nwhole -- so if there's a date/timestamp in there, that might confuse your logic. You can work\naround this by specifying %m %n as a layout and add the date later on in the appender. Or, make\nthe comparison smart enough to omit the date.\n\nAt last, don't forget what happens if the program is being shut down. If there's still messages\nin the buffer, they should be printed out at that point. That's easy to do in the appender's\nDESTROY method, which gets called at object destruction time:\n\nsub DESTROY {\nmy($self) = @;\n\nif($self->{lastmessagecount}) {\nprint \"[$self->{lastmessagecount}]: \" .\n\"$self->{lastmessage}\";\nreturn;\n}\n}\n\nThis will ensure that none of the buffered messages are lost. Happy buffering!\n\nI want to log ERROR and WARN messages to different files! How can I do that?\nLet's assume you wanted to have each logging statement written to a different file, based on the\nstatement's priority. Messages with priority \"WARN\" are supposed to go to \"/tmp/app.warn\",\nevents prioritized as \"ERROR\" should end up in \"/tmp/app.error\".\n\nNow, if you define two appenders \"AppWarn\" and \"AppError\" and assign them both to the root\nlogger, messages bubbling up from any loggers below will be logged by both appenders because of\nLog4perl's message propagation feature. If you limit their exposure via the appender threshold\nmechanism and set \"AppWarn\"'s threshold to \"WARN\" and \"AppError\"'s to \"ERROR\", you'll still get\n\"ERROR\" messages in \"AppWarn\", because \"AppWarn\"'s \"WARN\" setting will just filter out messages\nwith a *lower* priority than \"WARN\" -- \"ERROR\" is higher and will be allowed to pass through.\n\nWhat we need for this is a Log4perl *Custom Filter*, available with Log::Log4perl 0.30.\n\nBoth appenders need to verify that the priority of the oncoming messages exactly *matches* the\npriority the appender is supposed to log messages of. To accomplish this task, let's define two\ncustom filters, \"MatchError\" and \"MatchWarn\", which, when attached to their appenders, will\nlimit messages passed on to them to those matching a given priority:\n\nlog4perl.logger = WARN, AppWarn, AppError\n\n# Filter to match level ERROR\nlog4perl.filter.MatchError = Log::Log4perl::Filter::LevelMatch\nlog4perl.filter.MatchError.LevelToMatch  = ERROR\nlog4perl.filter.MatchError.AcceptOnMatch = true\n\n# Filter to match level WARN\nlog4perl.filter.MatchWarn  = Log::Log4perl::Filter::LevelMatch\nlog4perl.filter.MatchWarn.LevelToMatch  = WARN\nlog4perl.filter.MatchWarn.AcceptOnMatch = true\n\n# Error appender\nlog4perl.appender.AppError = Log::Log4perl::Appender::File\nlog4perl.appender.AppError.filename = /tmp/app.err\nlog4perl.appender.AppError.layout   = SimpleLayout\nlog4perl.appender.AppError.Filter   = MatchError\n\n# Warning appender\nlog4perl.appender.AppWarn = Log::Log4perl::Appender::File\nlog4perl.appender.AppWarn.filename = /tmp/app.warn\nlog4perl.appender.AppWarn.layout   = SimpleLayout\nlog4perl.appender.AppWarn.Filter   = MatchWarn\n\nThe appenders \"AppWarn\" and \"AppError\" defined above are logging to \"/tmp/app.warn\" and\n\"/tmp/app.err\" respectively and have the custom filters \"MatchWarn\" and \"MatchError\" attached.\nThis setup will direct all WARN messages, issued anywhere in the system, to /tmp/app.warn (and\nERROR messages to /tmp/app.error) -- without any overlaps.\n\nOn our server farm, Log::Log4perl configuration files differ slightly from host to host. Can I roll them all into one?\nYou sure can, because Log::Log4perl allows you to specify attribute values dynamically. Let's\nsay that one of your appenders expects the host's IP address as one of its attributes. Now, you\ncould certainly roll out different configuration files for every host and specify the value like\n\nlog4perl.appender.MyAppender    = Log::Log4perl::Appender::SomeAppender\nlog4perl.appender.MyAppender.ip = 10.0.0.127\n\nbut that's a maintenance nightmare. Instead, you can have Log::Log4perl figure out the IP\naddress at configuration time and set the appender's value correctly:\n\n# Set the IP address dynamically\nlog4perl.appender.MyAppender    = Log::Log4perl::Appender::SomeAppender\nlog4perl.appender.MyAppender.ip = sub { \\\nuse Sys::Hostname; \\\nuse Socket; \\\nreturn inetntoa(scalar gethostbyname hostname); \\\n}\n\nIf Log::Log4perl detects that an attribute value starts with something like \"sub {...\", it will\ninterpret it as a perl subroutine which is to be executed once at configuration time (not\nruntime!) and its return value is to be used as the attribute value. This comes in handy for\nrolling out applications where Log::Log4perl configuration files show small host-specific\ndifferences, because you can deploy the unmodified application distribution on all instances of\nthe server farm.\n\nLog4perl doesn't interpret my backslashes correctly!\nIf you're using Log4perl's feature to specify the configuration as a string in your program (as\nopposed to a separate configuration file), chances are that you've written it like this:\n\n# * WRONG! *\n\nLog::Log4perl->init( \\ <<ENDHERE);\nlog4perl.logger = WARN, A1\nlog4perl.appender.A1 = Log::Log4perl::Appender::Screen\nlog4perl.appender.A1.layout = \\\nLog::Log4perl::Layout::PatternLayout\nlog4perl.appender.A1.layout.ConversionPattern = %m%n\nENDHERE\n\n# * WRONG! *\n\nand you're getting the following error message:\n\nLayout not specified for appender A1 at .../Config.pm line 342.\n\nWhat's wrong? The problem is that you're using a here-document with substitution enabled\n(\"<<ENDHERE\") and that Perl won't interpret backslashes at line-ends as continuation characters\nbut will essentially throw them out. So, in the code above, the layout line will look like\n\nlog4perl.appender.A1.layout =\n\nto Log::Log4perl which causes it to report an error. To interpret the backslash at the end of\nthe line correctly as a line-continuation character, use the non-interpreting mode of the\nhere-document like in\n\n# * RIGHT! *\n\nLog::Log4perl->init( \\ <<'ENDHERE');\nlog4perl.logger = WARN, A1\nlog4perl.appender.A1 = Log::Log4perl::Appender::Screen\nlog4perl.appender.A1.layout = \\\nLog::Log4perl::Layout::PatternLayout\nlog4perl.appender.A1.layout.ConversionPattern = %m%n\nENDHERE\n\n# * RIGHT! *\n\n(note the single quotes around 'ENDHERE') or use \"q{...}\" instead of a here-document and Perl\nwill treat the backslashes at line-end as intended.\n\nI want to suppress certain messages based on their content!\nLet's assume you've plastered all your functions with Log4perl statements like\n\nsub somefunc {\n\nINFO(\"Begin of function\");\n\n# ... Stuff happens here ...\n\nINFO(\"End of function\");\n}\n\nto issue two log messages, one at the beginning and one at the end of each function. Now you\nwant to suppress the message at the beginning and only keep the one at the end, what can you do?\nYou can't use the category mechanism, because both messages are issued from the same package.\n\nLog::Log4perl's custom filters (0.30 or better) provide an interface for the Log4perl user to\nstep in right before a message gets logged and decide if it should be written out or suppressed,\nbased on the message content or other parameters:\n\nuse Log::Log4perl qw(:easy);\n\nLog::Log4perl::init( \\ <<'EOT' );\nlog4perl.logger             = INFO, A1\nlog4perl.appender.A1        = Log::Log4perl::Appender::Screen\nlog4perl.appender.A1.layout = \\\nLog::Log4perl::Layout::PatternLayout\nlog4perl.appender.A1.layout.ConversionPattern = %m%n\n\nlog4perl.filter.M1 = Log::Log4perl::Filter::StringMatch\nlog4perl.filter.M1.StringToMatch = Begin\nlog4perl.filter.M1.AcceptOnMatch = false\n\nlog4perl.appender.A1.Filter = M1\nEOT\n\nThe last four statements in the configuration above are defining a custom filter \"M1\" of type\n\"Log::Log4perl::Filter::StringMatch\", which comes with Log4perl right out of the box and allows\nyou to define a text pattern to match (as a perl regular expression) and a flag \"AcceptOnMatch\"\nindicating if a match is supposed to suppress the message or let it pass through.\n\nThe last line then assigns this filter to the \"A1\" appender, which will call it every time it\nreceives a message to be logged and throw all messages out *not* matching the regular expression\n\"Begin\".\n\nInstead of using the standard \"Log::Log4perl::Filter::StringMatch\" filter, you can define your\nown, simply using a perl subroutine:\n\nlog4perl.filter.ExcludeBegin  = sub { !/Begin/ }\nlog4perl.appender.A1.Filter   = ExcludeBegin\n\nFor details on custom filters, check Log::Log4perl::Filter.\n\nMy new module uses Log4perl -- but what happens if the calling program didn't configure it?\nIf a Perl module uses Log::Log4perl, it will typically rely on the calling program to initialize\nit. If it is using Log::Log4perl in \":easy\" mode, like in\n\npackage MyMod;\nuse Log::Log4perl qw(:easy);\n\nsub foo {\nDEBUG(\"In foo\");\n}\n\n1;\n\nand the calling program doesn't initialize Log::Log4perl at all (e.g. because it has no clue\nthat it's available), Log::Log4perl will silently ignore all logging messages. However, if the\nmodule is using Log::Log4perl in regular mode like in\n\npackage MyMod;\nuse Log::Log4perl qw(getlogger);\n\nsub foo {\nmy $logger = getlogger(\"\");\n$logger->debug(\"blah\");\n}\n\n1;\n\nand the main program is just using the module like in\n\nuse MyMode;\nMyMode::foo();\n\nthen Log::Log4perl will also ignore all logging messages but issue a warning like\n\nLog4perl: Seems like no initialization happened.\nForgot to call init()?\n\n(only once!) to remind novice users to not forget to initialize the logging system before using\nit. However, if you want to suppress this message, just add the \":nowarn\" target to the module's\n\"use Log::Log4perl\" call:\n\nuse Log::Log4perl qw(getlogger :nowarn);\n\nThis will have Log::Log4perl silently ignore all logging statements if no initialization has\ntaken place. If, instead of using init(), you're using Log4perl's API to define loggers and\nappenders, the same notification happens if no call to addappenders() is made, i.e. no\nappenders are defined.\n\nIf the module wants to figure out if some other program part has already initialized\nLog::Log4perl, it can do so by calling\n\nLog::Log4perl::initialized()\n\nwhich will return a true value in case Log::Log4perl has been initialized and a false value if\nnot.\n\nHow can I synchronize access to an appender?\nIf you're using the same instance of an appender in multiple processes, and each process is\npassing on messages to the appender in parallel, you might end up with overlapping log entries.\n\nTypical scenarios include a file appender that you create in the main program, and which will\nthen be shared between the parent and a forked child process. Or two separate processes, each\ninitializing a Log4perl file appender on the same logfile.\n\nLog::Log4perl won't synchronize access to the shared logfile by default. Depending on your\noperating system's flush mechanism, buffer size and the size of your messages, there's a small\nchance of an overlap.\n\nThe easiest way to prevent overlapping messages in logfiles written to by multiple processes is\nsetting the file appender's \"syswrite\" flag along with a file write mode of \"append\". This makes\nsure that \"Log::Log4perl::Appender::File\" uses \"syswrite()\" (which is guaranteed to run\nuninterrupted) instead of \"print()\" which might buffer the message or get interrupted by the OS\nwhile it is writing. And in \"append\" mode, the OS kernel ensures that multiple processes share\none end-of-file marker, ensuring that each process writes to the *real* end of the file. (The\nvalue of \"append\" for the \"mode\" parameter is the default setting in Log4perl's file appender so\nyou don't have to set it explicitly.)\n\n# Guarantees atomic writes\n\nlog4perl.category.Bar.Twix          = WARN, Logfile\n\nlog4perl.appender.Logfile           = Log::Log4perl::Appender::File\nlog4perl.appender.Logfile.mode      = append\nlog4perl.appender.Logfile.syswrite  = 1\nlog4perl.appender.Logfile.filename  = test.log\nlog4perl.appender.Logfile.layout    = SimpleLayout\n\nAnother guaranteed way of having messages separated with any kind of appender is putting a\nLog::Log4perl::Appender::Synchronized composite appender in between Log::Log4perl and the real\nappender. It will make sure to let messages pass through this virtual gate one by one only.\n\nHere's a sample configuration to synchronize access to a file appender:\n\nlog4perl.category.Bar.Twix          = WARN, Syncer\n\nlog4perl.appender.Logfile           = Log::Log4perl::Appender::File\nlog4perl.appender.Logfile.autoflush = 1\nlog4perl.appender.Logfile.filename  = test.log\nlog4perl.appender.Logfile.layout    = SimpleLayout\n\nlog4perl.appender.Syncer            = Log::Log4perl::Appender::Synchronized\nlog4perl.appender.Syncer.appender   = Logfile\n\n\"Log::Log4perl::Appender::Synchronized\" uses the \"IPC::Shareable\" module and its semaphores,\nwhich will slow down writing the log messages, but ensures sequential access featuring atomic\nchecks. Check Log::Log4perl::Appender::Synchronized for details.\n\nCan I use Log::Log4perl with log4j's Chainsaw?\nYes, Log::Log4perl can be configured to send its events to log4j's graphical log UI *Chainsaw*.\n",
                "subsections": []
            },
            "Figure1: Chainsaw receives Log::Log4perl events": {
                "content": "Here's how it works:\n\n*   Get Guido Carls' <gcarls@cpan.org> Log::Log4perl extension\n\"Log::Log4perl::Layout::XMLLayout\" from CPAN and install it:\n\nperl -MCPAN -eshell\ncpan> install Log::Log4perl::Layout::XMLLayout\n\n*   Install and start Chainsaw, which is part of the \"log4j\" distribution now (see\nhttp://jakarta.apache.org/log4j ). Create a configuration file like\n\n<log4j:configuration debug=\"true\">\n<plugin name=\"XMLSocketReceiver\"\nclass=\"org.apache.log4j.net.XMLSocketReceiver\">\n<param name=\"decoder\" value=\"org.apache.log4j.xml.XMLDecoder\"/>\n<param name=\"Port\" value=\"4445\"/>\n</plugin>\n<root> <level value=\"debug\"/> </root>\n</log4j:configuration>\n\nand name it e.g. \"config.xml\". Then start Chainsaw like\n\njava -Dlog4j.debug=true -Dlog4j.configuration=config.xml \\\n-classpath \".:log4j-1.3alpha.jar:log4j-chainsaw-1.3alpha.jar\" \\\norg.apache.log4j.chainsaw.LogUI\n\nand watch the GUI coming up.\n\n*   Configure Log::Log4perl to use a socket appender with an XMLLayout, pointing to the\nhost/port where Chainsaw (as configured above) is waiting with its XMLSocketReceiver:\n\nuse Log::Log4perl qw(getlogger);\nuse Log::Log4perl::Layout::XMLLayout;\n\nmy $conf = q(\nlog4perl.category.Bar.Twix          = WARN, Appender\nlog4perl.appender.Appender          = Log::Log4perl::Appender::Socket\nlog4perl.appender.Appender.PeerAddr = localhost\nlog4perl.appender.Appender.PeerPort = 4445\nlog4perl.appender.Appender.layout   = Log::Log4perl::Layout::XMLLayout\n);\n\nLog::Log4perl::init(\\$conf);\n\n# Nasty hack to suppress encoding header\nmy $app = Log::Log4perl::appenders->{\"Appender\"};\n$app->layout()->{encset} = 1;\n\nmy $logger = getlogger(\"Bar.Twix\");\n$logger->error(\"One\");\n\nThe nasty hack shown in the code snippet above is currently (October 2003) necessary,\nbecause Chainsaw expects XML messages to arrive in a format like\n\n<log4j:event logger=\"Bar.Twix\"\ntimestamp=\"1066794904310\"\nlevel=\"ERROR\"\nthread=\"10567\">\n<log4j:message><![CDATA[Two]]></log4j:message>\n<log4j:NDC><![CDATA[undef]]></log4j:NDC>\n<log4j:locationInfo class=\"main\"\nmethod=\"main\"\nfile=\"./t\"\nline=\"32\">\n</log4j:locationInfo>\n</log4j:event>\n\nwithout a preceding\n\n<?xml version = \"1.0\" encoding = \"iso8859-1\"?>\n\nwhich Log::Log4perl::Layout::XMLLayout applies to the first event sent over the socket.\n\nSee figure 1 for a screenshot of Chainsaw in action, receiving events from the Perl script shown\nabove.\n\nMany thanks to Chainsaw's Scott Deboy <sdeboy@comotivsystems.com> for his support!\n\nHow can I run Log::Log4perl under modperl?\nIn persistent environments it's important to play by the rules outlined in section \"Initialize\nonce and only once\" in Log::Log4perl. If you haven't read this yet, please go ahead and read it\nright now. It's very important.\n\nAnd no matter if you use a startup handler to init() Log::Log4perl or use the initonce()\nstrategy (added in 0.42), either way you're very likely to have unsynchronized writes to\nlogfiles.\n\nIf Log::Log4perl is configured with a log file appender, and it is initialized via the Apache\nstartup handler, the file handle created initially will be shared among all Apache processes.\nSimilarly, with the initonce() approach: although every process has a separate L4p\nconfiguration, processes are gonna share the appender file *names* instead, effectively opening\nseveral different file handles on the same file.\n\nNow, having several appenders using the same file handle or having several appenders logging to\nthe same file unsynchronized, this might result in overlapping messages. Sometimes, this is\nacceptable. If it's not, here's two strategies:\n\n*   Use the Log::Log4perl::Appender::Synchronized appender to connect to your file appenders.\nHere's the writeup:\nhttp://log4perl.sourceforge.net/releases/Log-Log4perl/docs/html/Log/Log4perl/FAQ.html#23804\n\n*   Use a different logfile for every process like in\n\n#log4perl.conf\n...\nlog4perl.appender.A1.filename = sub { \"mylog.$$.log\" }\n\nMy program already uses warn() and die(). How can I switch to Log4perl?\nIf your program already uses Perl's \"warn()\" function to spew out error messages and you'd like\nto channel those into the Log4perl world, just define a \"WARN\" handler where your program or\nmodule resides:\n\nuse Log::Log4perl qw(:easy);\n\n$SIG{WARN} = sub {\nlocal $Log::Log4perl::callerdepth =\n$Log::Log4perl::callerdepth + 1;\nWARN @;\n};\n\nWhy the \"local\" setting of $Log::Log4perl::callerdepth? If you leave that out, \"PatternLayout\"\nconversion specifiers like %M or %F (printing the current function/method and source filename)\nwill refer to where the WARN handler resides, not the environment Perl's \"warn()\" function\nwas issued from. Increasing \"callerdepth\" adjusts for this offset. Having it \"local\", makes\nsure the level gets set back after the handler exits.\n\nOnce done, if your program does something like\n\nsub somefunc {\nwarn \"Here's a warning\";\n}\n\nyou'll get (depending on your Log::Log4perl configuration) something like\n\n2004/02/19 20:41:02-main::somefunc: Here's a warning at ./t line 25.\n\nin the appropriate appender instead of having a screen full of STDERR messages. It also works\nwith the \"Carp\" module and its \"carp()\" and \"cluck()\" functions.\n\nIf, on the other hand, catching \"die()\" and friends is required, a \"DIE\" handler is\nappropriate:\n\n$SIG{DIE} = sub {\nif($^S) {\n# We're in an eval {} and don't want log\n# this message but catch it later\nreturn;\n}\nlocal $Log::Log4perl::callerdepth =\n$Log::Log4perl::callerdepth + 1;\nLOGDIE @;\n};\n\nThis will call Log4perl's \"LOGDIE()\" function, which will log a fatal error and then call die()\ninternally, causing the program to exit. Works equally well with \"Carp\"'s \"croak()\" and\n\"confess()\" functions.\n\nSome module prints messages to STDERR. How can I funnel them to Log::Log4perl?\nIf a module you're using doesn't use Log::Log4perl but prints logging messages to STDERR\ninstead, like\n\n########################################\npackage IgnorantModule;\n########################################\n\nsub somemethod {\nprint STDERR \"Parbleu! An error!\\n\";\n}\n\n1;\n\nthere's still a way to capture these messages and funnel them into Log::Log4perl, even without\ntouching the module. What you need is a trapper module like\n\n########################################\npackage Trapper;\n########################################\n\nuse Log::Log4perl qw(:easy);\n\nsub TIEHANDLE {\nmy $class = shift;\nbless [], $class;\n}\n\nsub PRINT {\nmy $self = shift;\n$Log::Log4perl::callerdepth++;\nDEBUG @;\n$Log::Log4perl::callerdepth--;\n}\n\n1;\n\nand a \"tie\" command in the main program to tie STDERR to the trapper module along with regular\nLog::Log4perl initialization:\n\n########################################\npackage main;\n########################################\n\nuse Log::Log4perl qw(:easy);\n\nLog::Log4perl->easyinit(\n{level  => $DEBUG,\nfile   => 'stdout',   # make sure not to use stderr here!\nlayout => \"%d %M: %m%n\",\n});\n\ntie *STDERR, \"Trapper\";\n\nMake sure not to use STDERR as Log::Log4perl's file appender here (which would be the default in\n\":easy\" mode), because it would end up in an endless recursion.\n\nNow, calling\n\nIgnorantModule::somemethod();\n\nwill result in the desired output\n\n2004/05/06 11:13:04 IgnorantModule::somemethod: Parbleu! An error!\n\nHow come PAR (Perl Archive Toolkit) creates executables which then can't find their Log::Log4perl appenders?\nIf not instructed otherwise, \"Log::Log4perl\" dynamically pulls in appender classes found in its\nconfiguration. If you specify\n\n#!/usr/bin/perl\n# mytest.pl\n\nuse Log::Log4perl qw(getlogger);\n\nmy $conf = q(\nlog4perl.category.Bar.Twix = WARN, Logfile\nlog4perl.appender.Logfile  = Log::Log4perl::Appender::Screen\nlog4perl.appender.Logfile.layout = SimpleLayout\n);\n\nLog::Log4perl::init(\\$conf);\nmy $logger = getlogger(\"Bar::Twix\");\n$logger->error(\"Blah\");\n\nthen \"Log::Log4perl::Appender::Screen\" will be pulled in while the program runs, not at compile\ntime. If you have PAR compile the script above to an executable binary via\n\npp -o mytest mytest.pl\n\nand then run \"mytest\" on a machine without having Log::Log4perl installed, you'll get an error\nmessage like\n\nERROR: can't load appenderclass 'Log::Log4perl::Appender::Screen'\nCan't locate Log/Log4perl/Appender/Screen.pm in @INC ...\n\nWhy? At compile time, \"pp\" didn't realize that \"Log::Log4perl::Appender::Screen\" would be needed\nlater on and didn't wrap it into the executable created. To avoid this, either say \"use\nLog::Log4perl::Appender::Screen\" in the script explicitly or compile it with\n\npp -o mytest -M Log::Log4perl::Appender::Screen mytest.pl\n\nto make sure the appender class gets included.\n\nHow can I access a custom appender defined in the configuration?\nAny appender defined in the configuration file or somewhere in the code can be accessed later\nvia \"Log::Log4perl->appenderbyname(\"appendername\")\", which returns a reference of the\nappender object.\n\nOnce you've got a hold of the object, it can be queried or modified to your liking. For example,\nsee the custom \"IndentAppender\" defined below: After calling \"init()\" to define the Log4perl\nsettings, the appender object is retrieved to call its \"indentmore()\" and \"indentless()\"\nmethods to control indentation of messages:\n\npackage IndentAppender;\n\nsub new {\nbless { indent => 0 }, $[0];\n}\n\nsub indentmore  { $[0]->{indent}++ }\nsub indentless  { $[0]->{indent}-- }\n\nsub log {\nmy($self, %params) = @;\nprint \" \" x $self->{indent}, $params{message};\n}\n\npackage main;\n\nuse Log::Log4perl qw(:easy);\n\nmy $conf = q(\nlog4perl.category          = DEBUG, Indented\nlog4perl.appender.Indented = IndentAppender\nlog4perl.appender.Indented.layout = Log::Log4perl::Layout::SimpleLayout\n);\n\nLog::Log4perl::init(\\$conf);\n\nmy $appender = Log::Log4perl->appenderbyname(\"Indented\");\n\nDEBUG \"No indentation\";\n$appender->indentmore();\nDEBUG \"One more\";\n$appender->indentmore();\nDEBUG \"Two more\";\n$appender->indentless();\nDEBUG \"One less\";\n\nAs you would expect, this will print\n\nDEBUG - No indentation\nDEBUG - One more\nDEBUG - Two more\nDEBUG - One less\n\nbecause the very appender used by Log4perl is modified dynamically at runtime.\n\nI don't know if Log::Log4perl is installed. How can I prepare my script?\nIn case your script needs to be prepared for environments that may or may not have Log::Log4perl\ninstalled, there's a trick.\n\nIf you put the following BEGIN blocks at the top of the program, you'll be able to use the\nDEBUG(), INFO(), etc. macros in Log::Log4perl's \":easy\" mode. If Log::Log4perl is installed in\nthe target environment, the regular Log::Log4perl rules apply. If not, all of DEBUG(), INFO(),\netc. are \"stubbed\" out, i.e. they turn into no-ops:\n\nuse warnings;\nuse strict;\n\nBEGIN {\neval { require Log::Log4perl; };\n\nif($@) {\nprint \"Log::Log4perl not installed - stubbing.\\n\";\nno strict qw(refs);\n*{\"main::$\"} = sub { } for qw(DEBUG INFO WARN ERROR FATAL);\n} else {\nno warnings;\nprint \"Log::Log4perl installed - life is good.\\n\";\nrequire Log::Log4perl::Level;\nLog::Log4perl::Level->import(PACKAGE);\nLog::Log4perl->import(qw(:easy));\nLog::Log4perl->easyinit($main::DEBUG);\n}\n}\n\n# The regular script begins ...\nDEBUG \"Hey now!\";\n\nThis snippet will first probe for Log::Log4perl, and if it can't be found, it will alias\nDEBUG(), INFO(), with empty subroutines via typeglobs. If Log::Log4perl is available, its level\nconstants are first imported ($DEBUG, $INFO, etc.) and then \"easyinit()\" gets called to\ninitialize the logging system.\n\nCan file appenders create files with different permissions?\nTypically, when \"Log::Log4perl::Appender::File\" creates a new file, its permissions are set to\n\"rw-r--r--\". Why? Because your environment's *umask* most likely defaults to 0022, that's the\nstandard setting.\n\nWhat's a *umask*, you're asking? It's a template that's applied to the permissions of all newly\ncreated files. While calls like \"open(FILE, \">foo\")\" will always try to create files in\n\"rw-rw-rw- \" mode, the system will apply the current *umask* template to determine the final\npermission setting. *umask* is a bit mask that's inverted and then applied to the requested\npermission setting, using a bitwise AND:\n\n$requestpermission &~ $umask\n\nSo, a *umask* setting of 0000 (the leading 0 simply indicates an octal value) will create files\nin \"rw-rw-rw-\" mode, a setting of 0277 will use \"r--------\", and the standard 0022 will use\n\"rw-r--r--\".\n\nAs an example, if you want your log files to be created with \"rw-r--rw-\" permissions, use a\n*umask* of 0020 before calling Log::Log4perl->init():\n\nuse Log::Log4perl;\n\numask 0020;\n# Creates log.out in rw-r--rw mode\nLog::Log4perl->init(\\ q{\nlog4perl.logger = WARN, File\nlog4perl.appender.File = Log::Log4perl::Appender::File\nlog4perl.appender.File.filename = log.out\nlog4perl.appender.File.layout = SimpleLayout\n});\n\nUsing Log4perl in an END block causes a problem!\nIt's not easy to get to this error, but if you write something like\n\nEND { Log::Log4perl::getlogger()->debug(\"Hey there.\"); }\n\nuse Log::Log4perl qw(:easy);\nLog::Log4perl->easyinit($DEBUG);\n\nit won't work. The reason is that \"Log::Log4perl\" defines an END block that cleans up all\nloggers. And perl will run END blocks in the reverse order as they're encountered in the compile\nphase, so in the scenario above, the END block will run *after* Log4perl has cleaned up its\nloggers.\n\nPlacing END blocks using Log4perl *after* a \"use Log::Log4perl\" statement fixes the problem:\n\nuse Log::Log4perl qw(:easy);\nLog::Log4perl->easyinit($DEBUG);\n\nEND { Log::Log4perl::getlogger()->debug(\"Hey there.\"); }\n\nIn this scenario, the shown END block is executed *before* Log4perl cleans up and the debug\nmessage will be processed properly.\n\nHelp! My appender is throwing a \"Wide character in print\" warning!\nThis warning shows up when Unicode strings are printed without precautions. The warning goes\naway if the complaining appender is set to utf-8 mode:\n\n# Either in the log4perl configuration file:\nlog4perl.appender.Logfile.filename = test.log\nlog4perl.appender.Logfile.utf8     = 1\n\n# Or, in easy mode:\nLog::Log4perl->easyinit( {\nlevel => $DEBUG,\nfile  => \":utf8> test.log\"\n} );\n\nIf the complaining appender is a screen appender, set its \"utf8\" option:\n\nlog4perl.appender.Screen.stderr = 1\nlog4perl.appender.Screen.utf8   = 1\n\nAlternatively, \"binmode\" does the trick:\n\n# Either STDOUT ...\nbinmode(STDOUT, \":utf8);\n\n# ... or STDERR.\nbinmode(STDERR, \":utf8);\n\nSome background on this: Perl's strings are either byte strings or Unicode strings. \"Mike\" is a\nbyte string. \"\\x{30DE}\\x{30A4}\\x{30AF}\" is a Unicode string. Unicode strings are marked\nspecially and are UTF-8 encoded internally.\n\nIf you print a byte string to STDOUT, all is well, because STDOUT is by default set to byte\nmode. However, if you print a Unicode string to STDOUT without precautions, \"perl\" will try to\ntransform the Unicode string back to a byte string before printing it out. This is troublesome\nif the Unicode string contains 'wide' characters which can't be represented in Latin-1.\n\nFor example, if you create a Unicode string with three japanese Katakana characters as in\n\nperl -le 'print \"\\x{30DE}\\x{30A4}\\x{30AF}\"'\n\n(coincidentally pronounced Ma-i-ku, the japanese pronunciation of \"Mike\"), STDOUT is in byte\nmode and the warning\n\nWide character in print at ./script.pl line 14.\n\nappears. Setting STDOUT to UTF-8 mode as in\n\nperl -le 'binmode(STDOUT, \":utf8\"); print \"\\x{30DE}\\x{30A4}\\x{30AF}\"'\n\nwill silently print the Unicode string to STDOUT in UTF-8. To see the characters printed, you'll\nneed a UTF-8 terminal with a font including japanese Katakana characters.\n\nHow can I send errors to the screen, and debug messages to a file?\nLet's assume you want to maintain a detailed DEBUG output in a file and only messages of level\nERROR and higher should be printed on the screen. Often times, developers come up with something\nlike this:\n\n# Wrong!!!\nlog4perl.logger = DEBUG, FileApp\nlog4perl.logger = ERROR, ScreenApp\n# Wrong!!!\n\nThis won't work, however. Logger definitions aren't additive, and the second statement will\noverwrite the first one. Log4perl versions below 1.04 were silently accepting this, leaving\npeople confused why it wouldn't work as expected. As of 1.04, this will throw a *fatal error* to\nnotify the user of the problem.\n\nWhat you want to do instead, is this:\n\nlog4perl.logger                    = DEBUG, FileApp, ScreenApp\n\nlog4perl.appender.FileApp          = Log::Log4perl::Appender::File\nlog4perl.appender.FileApp.filename = test.log\nlog4perl.appender.FileApp.layout   = SimpleLayout\n\nlog4perl.appender.ScreenApp          = Log::Log4perl::Appender::Screen\nlog4perl.appender.ScreenApp.stderr   = 0\nlog4perl.appender.ScreenApp.layout   = SimpleLayout\n### limiting output to ERROR messages\nlog4perl.appender.ScreenApp.Threshold = ERROR\n###\n\nNote that without the second appender's \"Threshold\" setting, both appenders would receive all\nmessages prioritized DEBUG and higher. With the threshold set to ERROR, the second appender will\nfilter the messages as required.\n\nWhere should I put my logfiles?\nYour log files may go anywhere you want them, but the effective user id of the calling process\nmust have write access.\n\nIf the log file doesn't exist at program start, Log4perl's file appender will create it. For\nthis, it needs write access to the directory where the new file will be located in. If the log\nfile already exists at startup, the process simply needs write access to the file. Note that it\nwill need write access to the file's directory if you're encountering situations where the\nlogfile gets recreated, e.g. during log rotation.\n\nIf Log::Log4perl is used by a web server application (e.g. in a CGI script or modperl), then\nthe webserver's user (usually \"nobody\" or \"www\") must have the permissions mentioned above.\n\nTo prepare your web server to use log4perl, we'd recommend:\n\nwebserver:~$ su -\nwebserver:~# mkdir /var/log/cgiapps\nwebserver:~# chown nobody:root /var/log/cgiapps/\nwebserver:~# chown nobody:root -R /var/log/cgiapps/\nwebserver:~# chmod 02755 -R /var/log/cgiapps/\n\nThen set your /etc/log4perl.conf file to include:\n\nlog4perl.appender.FileAppndr1.filename =\n/var/log/cgiapps/<app-name>.log\n\nHow can my file appender deal with disappearing log files?\nThe file appender that comes with Log4perl, Log::Log4perl::Appender::File, will open a specified\nlog file at initialization time and will keep writing to it via a file handle.\n\nIn case the associated file goes way, messages written by a long-running process will still be\nwritten to the file handle. In case the file has been moved to a different location on the same\nfile system, the writer will keep writing to it under the new filename. In case the file has\nbeen removed from the file system, the log messages will end up in nowhere land. This is not a\nbug in Log4perl, this is how Unix works. There is no error message in this case, because the\nwriter has no idea that the file handle is not associated with a visible file.\n\nTo prevent the loss of log messages when log files disappear, the file appender's \"recreate\"\noption needs to be set to a true value:\n\nlog4perl.appender.Logfile.recreate = 1\n\nThis will instruct the file appender to check in regular intervals (default: 30 seconds) if the\nlog file is still there. If it finds out that the file is missing, it will recreate it.\n\nContinuously checking if the log file still exists is fairly expensive. For this reason it is\nonly performed every 30 seconds. To change this interval, the option \"recreatecheckinterval\"\ncan be set to the number of seconds between checks. In the extreme case where the check should\nbe performed before every write, it can even be set to 0:\n\nlog4perl.appender.Logfile.recreate = 1\nlog4perl.appender.Logfile.recreatecheckinterval = 0\n\nTo avoid having to check the file system so frequently, a signal handler can be set up:\n\nlog4perl.appender.Logfile.recreate = 1\nlog4perl.appender.Logfile.recreatechecksignal = USR1\n\nThis will install a signal handler which will recreate a missing log file immediately when it\nreceives the defined signal.\n\nNote that the initandwatch() method for Log4perl's initialization can also be instructed to\ninstall a signal handler, usually using the HUP signal. Make sure to use a different signal if\nyou're using both of them at the same time.\n\nHow can I rotate a logfile with newsyslog?\nHere's a few things that need to be taken care of when using the popular log file rotating\nutility \"newsyslog\" (http://www.courtesan.com/newsyslog) with Log4perl's file appender in\nlong-running processes.\n\nFor example, with a newsyslog configuration like\n\n# newsyslog.conf\n/tmp/test.log 666  12  5  *  B\n\nand a call to\n\n# newsyslog -f /path/to/newsyslog.conf\n\n\"newsyslog\" will take action if \"/tmp/test.log\" is larger than the specified 5K in size. It will\nmove the current log file \"/tmp/test.log\" to \"/tmp/test.log.0\" and create a new and empty\n\"/tmp/test.log\" with the specified permissions (this is why \"newsyslog\" needs to run as root).\nAn already existing \"/tmp/test.log.0\" would be moved to \"/tmp/test.log.1\", \"/tmp/test.log.1\" to\n\"/tmp/test.log.2\", and so forth, for every one of a max number of 12 archived logfiles that have\nbeen configured in \"newsyslog.conf\".\n\nAlthough a new file has been created, from Log4perl's appender's point of view, this situation\nis identical to the one described in the previous FAQ entry, labeled \"How can my file appender\ndeal with disappearing log files\".\n\nTo make sure that log messages are written to the new log file and not to an archived one or end\nup in nowhere land, the appender's \"recreate\" and \"recreatecheckinterval\" have to be\nconfigured to deal with the 'disappearing' log file.\n\nThe situation gets interesting when \"newsyslog\"'s option to compress archived log files is\nenabled. This causes the original log file not to be moved, but to disappear. If the file\nappender isn't configured to recreate the logfile in this situation, log messages will actually\nbe lost without warning. This also applies for the short time frame of \"recreatecheckinterval\"\nseconds in between the recreator's file checks.\n\nTo make sure that no messages get lost, one option is to set the interval to\n\nlog4perl.appender.Logfile.recreatecheckinterval = 0\n\nHowever, this is fairly expensive. A better approach is to define a signal handler:\n\nlog4perl.appender.Logfile.recreate = 1\nlog4perl.appender.Logfile.recreatechecksignal  = USR1\nlog4perl.appender.Logfile.recreatepidwrite = /tmp/myappid\n\nAs a service for \"newsyslog\" users, Log4perl's file appender writes the current process ID to a\nPID file specified by the \"recreatepidwrite\" option. \"newsyslog\" then needs to be configured\nas in\n\n# newsyslog.conf configuration for compressing archive files and\n# sending a signal to the Log4perl-enabled application\n/tmp/test.log 666  12  5  *  B /tmp/myappid 30\n\nto send the defined signal (30, which is USR1 on FreeBSD) to the application process at rotation\ntime. Note that the signal number is different on Linux, where USR1 denotes as 10. Check \"man\nsignal\" for details.\n\nHow can a process under user id A log to a file under user id B?\nThis scenario often occurs in configurations where processes run under various user IDs but need\nto write to a log file under a fixed, but different user id.\n\nWith a traditional file appender, the log file will probably be created under one user's id and\nappended to under a different user's id. With a typical umask of 0002, the file will be created\nwith -rw-rw-r-- permissions. If a user who's not in the first user's group subsequently appends\nto the log file, it will fail because of a permission problem.\n\nTwo potential solutions come to mind:\n\n*   Creating the file with a umask of 0000 will allow all users to append to the log file.\nLog4perl's file appender \"Log::Log4perl::Appender::File\" has an \"umask\" option that can be\nset to support this:\n\nlog4perl.appender.File = Log::Log4perl::Appender::File\nlog4perl.appender.File.umask = sub { 0000 };\n\nThis way, the log file will be created with -rw-rw-rw- permissions and therefore has world\nwrite permissions. This might open up the logfile for unwanted manipulations by arbitrary\nusers, though.\n\n*   Running the process under an effective user id of \"root\" will allow it to write to the log\nfile, no matter who started the process. However, this is not a good idea, because of\nsecurity concerns.\n\nLuckily, under Unix, there's the syslog daemon which runs as root and takes log requests from\nuser processes over a socket and writes them to log files as configured in \"/etc/syslog.conf\".\n\nBy modifying \"/etc/syslog.conf\" and HUPing the syslog daemon, you can configure new log files:\n\n# /etc/syslog.conf\n...\nuser.* /some/path/file.log\n\nUsing the \"Log::Dispatch::Syslog\" appender, which comes with the \"Log::Log4perl\" distribution,\nyou can then send messages via syslog:\n\nuse Log::Log4perl qw(:easy);\n\nLog::Log4perl->init(\\<<EOT);\nlog4perl.logger = DEBUG, app\nlog4perl.appender.app=Log::Dispatch::Syslog\nlog4perl.appender.app.Facility=user\nlog4perl.appender.app.layout=SimpleLayout\nEOT\n\n# Writes to /some/path/file.log\nERROR \"Message!\";\n\nThis way, the syslog daemon will solve the permission problem.\n\nNote that while it is possible to use syslog() without Log4perl (syslog supports log levels,\ntoo), traditional syslog setups have a significant drawback.\n\nWithout Log4perl's ability to activate logging in only specific parts of a system, complex\nsystems will trigger log events all over the place and slow down execution to a crawl at high\ndebug levels.\n\nRemote-controlling logging in the hierarchical parts of an application via Log4perl's categories\nis one of its most distinguished features. It allows for enabling high debug levels in specified\nareas without noticeable performance impact.\n\nI want to use UTC instead of the local time!\nIf a layout defines a date, Log::Log4perl uses local time to populate it. If you want UTC\ninstead, set\n\nlog4perl.utcDateTimes = 1\n\nin your configuration. Alternatively, you can set\n\n$Log::Log4perl::DateFormat::GMTIME = 1;\n\nin your program before the first log statement.\n\nCan Log4perl intercept messages written to a filehandle?\nYou have a function that prints to a filehandle. You want to tie into that filehandle and\nforward all arriving messages to a Log4perl logger.\n\nFirst, let's write a package that ties a file handle and forwards it to a Log4perl logger:\n\npackage FileHandleLogger;\nuse Log::Log4perl qw(:levels getlogger);\n\nsub TIEHANDLE {\nmy($class, %options) = @;\n\nmy $self = {\nlevel    => $DEBUG,\ncategory => '',\n%options\n};\n\n$self->{logger} = getlogger($self->{category}),\nbless $self, $class;\n}\n\nsub PRINT {\nmy($self, @rest) = @;\n$Log::Log4perl::callerdepth++;\n$self->{logger}->log($self->{level}, @rest);\n$Log::Log4perl::callerdepth--;\n}\n\nsub PRINTF {\nmy($self, $fmt, @rest) = @;\n$Log::Log4perl::callerdepth++;\n$self->PRINT(sprintf($fmt, @rest));\n$Log::Log4perl::callerdepth--;\n}\n\n1;\n\nNow, if you have a function like\n\nsub functionprintingtofh {\nmy($fh) = @;\nprintf $fh \"Hi there!\\n\";\n}\n\nwhich takes a filehandle and prints something to it, it can be used with Log4perl:\n\nuse Log::Log4perl qw(:easy);\nusa FileHandleLogger;\n\nLog::Log4perl->easyinit($DEBUG);\n\ntie *SOMEHANDLE, 'FileHandleLogger' or\ndie \"tie failed ($!)\";\n\nfunctionprintingtofh(*SOMEHANDLE);\n# prints \"2007/03/22 21:43:30 Hi there!\"\n\nIf you want, you can even specify a different log level or category:\n\ntie *SOMEHANDLE, 'FileHandleLogger',\nlevel => $INFO, category => \"Foo::Bar\" or die \"tie failed ($!)\";\n\nI want multiline messages rendered line-by-line!\nWith the standard \"PatternLayout\", if you send a multiline message to an appender as in\n\nuse Log::Log4perl qw(:easy);\nLog\n\nit gets rendered this way:\n\n2007/04/04 23:23:39 multi\nline\nmessage\n\nIf you want each line to be rendered separately according to the layout use\n\"Log::Log4perl::Layout::PatternLayout::Multiline\":\n\nuse Log::Log4perl qw(:easy);\n\nLog::Log4perl->init(\\<<EOT);\nlog4perl.category         = DEBUG, Screen\nlog4perl.appender.Screen = Log::Log4perl::Appender::Screen\nlog4perl.appender.Screen.layout = \\\\\nLog::Log4perl::Layout::PatternLayout::Multiline\nlog4perl.appender.Screen.layout.ConversionPattern = %d %m %n\nEOT\n\nDEBUG \"some\\nmultiline\\nmessage\";\n\nand you'll get\n\n2007/04/04 23:23:39 some\n2007/04/04 23:23:39 multiline\n2007/04/04 23:23:39 message\n\ninstead.\n\nI'm on Windows and I'm getting all these 'redefined' messages!\nIf you're on Windows and are getting warning messages like\n\nConstant subroutine Log::Log4perl::INTERNALDEBUG redefined at\nC:/Programme/Perl/lib/constant.pm line 103.\nSubroutine import redefined at\nC:/Programme/Perl/site/lib/Log/Log4Perl.pm line 69.\nSubroutine initialized redefined at\nC:/Programme/Perl/site/lib/Log/Log4Perl.pm line 207.\n\nthen chances are that you're using 'Log::Log4Perl' (wrong uppercase P) instead of the correct\n'Log::Log4perl'. Perl on Windows doesn't handle this error well and spits out a slew of\nconfusing warning messages. But now you know, just use the correct module name and you'll be\nfine.\n\nLog4perl complains that no initialization happened during shutdown!\nIf you're using Log4perl log commands in DESTROY methods of your objects, you might see\nconfusing messages like\n\nLog4perl: Seems like no initialization happened. Forgot to call init()?\nUse of uninitialized value in subroutine entry at\n/home/y/lib/perl5/siteperl/5.6.1/Log/Log4perl.pm line 134 during global\ndestruction. (in cleanup) Undefined subroutine &main:: called at\n/home/y/lib/perl5/siteperl/5.6.1/Log/Log4perl.pm line 134 during global\ndestruction.\n\nwhen the program shuts down. What's going on?\n\nThis phenomenon happens if you have circular references in your objects, which perl can't clean\nup when an object goes out of scope but waits until global destruction instead. At this time,\nhowever, Log4perl has already shut down, so you can't use it anymore.\n\nFor example, here's a simple class which uses a logger in its DESTROY method:\n\npackage A;\nuse Log::Log4perl qw(:easy);\nsub new { bless {}, shift }\nsub DESTROY { DEBUG \"Waaah!\"; }\n\nNow, if the main program creates a self-referencing object, like in\n\npackage main;\nuse Log::Log4perl qw(:easy);\nLog::Log4perl->easyinit($DEBUG);\n\nmy $a = A->new();\n$a->{selfref} = $a;\n\nthen you'll see the error message shown above during global destruction. How to tackle this\nproblem?\n\nFirst, you should clean up your circular references before global destruction. They will not\nonly cause objects to be destroyed in an order that's hard to predict, but also eat up memory\nuntil the program shuts down.\n\nSo, the program above could easily be fixed by putting\n\n$a->{selfref} = undef;\n\nat the end or in an END handler. If that's hard to do, use weak references:\n\npackage main;\nuse Scalar::Util qw(weaken);\nuse Log::Log4perl qw(:easy);\nLog::Log4perl->easyinit($DEBUG);\n\nmy $a = A->new();\n$a->{selfref} = weaken $a;\n\nThis allows perl to clean up the circular reference when the object goes out of scope, and\ndoesn't wait until global destruction.\n\nHow can I access POE heap values from Log4perl's layout?\nPOE is a framework for creating multitasked applications running in a single process and a\nsingle thread. POE's threads equivalents are 'sessions' and since they run quasi-simultaneously,\nyou can't use Log4perl's global NDC/MDC to hold session-specific data.\n\nHowever, POE already maintains a data store for every session. It is called 'heap' and is just a\nhash storing session-specific data in key-value pairs. To access this per-session heap data from\na Log4perl layout, define a custom cspec and reference it with the newly defined pattern in the\nlayout:\n\nuse strict;\nuse POE;\nuse Log::Log4perl qw(:easy);\n\nLog::Log4perl->init( \\ q{\nlog4perl.logger = DEBUG, Screen\nlog4perl.appender.Screen = Log::Log4perl::Appender::Screen\nlog4perl.appender.Screen.layout = PatternLayout\nlog4perl.appender.Screen.layout.ConversionPattern = %U %m%n\nlog4perl.PatternLayout.cspec.U = \\\nsub { POE::Kernel->getactivesession->getheap()->{ user } }\n} );\n\nfor (qw( Huey Lewey Dewey )) {\nPOE::Session->create(\ninlinestates => {\nstart    => sub {\n$[HEAP]->{user} = $;\nPOE::Kernel->yield('hello');\n},\nhello     => sub {\nDEBUG \"I'm here now\";\n}\n}\n);\n}\n\nPOE::Kernel->run();\nexit;\n\nThe code snippet above defines a new layout placeholder (called 'cspec' in Log4perl) %U which\ncalls a subroutine, retrieves the active session, gets its heap and looks up the entry specified\n('user').\n\nStarting with Log::Log4perl 1.20, cspecs also support parameters in curly braces, so you can say\n\nlog4perl.appender.Screen.layout.ConversionPattern = %U{user} %U{id} %m%n\nlog4perl.PatternLayout.cspec.U = \\\nsub { POE::Kernel->getactivesession-> \\\ngetheap()->{ $[0]->{curlies} } }\n\nand print the POE session heap entries 'user' and 'id' with every logged message. For more\ndetails on cpecs, read the PatternLayout manual.\n\nI want to print something unconditionally!\nSometimes it's a script that's supposed to log messages regardless if Log4perl has been\ninitialized or not. Or there's a logging statement that's not going to be suppressed under any\ncircumstances -- many people want to have the final word, make the executive decision, because\nit seems like the only logical choice.\n\nBut think about it: First off, if a messages is supposed to be printed, where is it supposed to\nend up at? STDOUT? STDERR? And are you sure you want to set in stone that this message needs to\nbe printed, while someone else might find it annoying and wants to get rid of it?\n\nThe truth is, there's always going to be someone who wants to log a messages at all cost, but\nalso another person who wants to suppress it with equal vigilance. There's no good way to serve\nthese two conflicting desires, someone will always want to win at the cost of leaving the other\nparty disappointed.\n\nSo, the best Log4perl offers is the ALWAYS level for a message that even fires if the system log\nlevel is set to $OFF:\n\nuse Log::Log4perl qw(:easy);\n\nLog::Log4perl->easyinit( $OFF );\nALWAYS \"This gets logged always. Well, almost always\";\n\nThe logger won't fire, though, if Log4perl hasn't been initialized or if someone defines a\ncustom log hurdle that's higher than $OFF.\n\nBottom line: Leave the setting of the logging level to the initial Perl script -- let their\nowners decided what they want, no matter how tempting it may be to decide it for them.\n\nWhy doesn't my END handler remove my log file on Win32?\nIf you have code like\n\nuse Log::Log4perl qw( :easy );\nLog::Log4perl->easyinit( { level => $DEBUG, file => \"my.log\" } );\nEND { unlink \"my.log\" or die };\n\nthen you might be in for a surprise when you're running it on Windows, because the \"unlink()\"\ncall in the END handler will complain that the file is still in use.\n\nWhat happens in Perl if you have something like\n\nEND { print \"first end in main\\n\"; }\nuse Module;\nEND { print \"second end in main\\n\"; }\n\nand\n\npackage Module;\nEND { print \"end in module\\n\"; }\n1;\n\nis that you get\n\nsecond end in main\nend in module\nfirst end in main\n\nbecause perl stacks the END handlers in reverse order in which it encounters them in the compile\nphase.\n\nLog4perl defines an END handler that cleans up left-over appenders (e.g. file appenders which\nstill hold files open), because those appenders have circular references and therefore aren't\ncleaned up otherwise.\n\nNow if you define an END handler after \"use Log::Log4perl\", it'll trigger before Log4perl gets a\nchance to clean up, which isn't a problem on Unix where you can delete a file even if some\nprocess has a handle to it open, but it's a problem on Win32, where the OS won't let you do\nthat.\n\nThe solution is easy, just place the END handler *before* Log4perl gets loaded, like in\n\nEND { unlink \"my.log\" or die };\nuse Log::Log4perl qw( :easy );\nLog::Log4perl->easyinit( { level => $DEBUG, file => \"my.log\" } );\n\nwhich will call the END handlers in the intended order.\n",
                "subsections": []
            },
            "SEE ALSO": {
                "content": "Log::Log4perl\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": []
            }
        }
    }
}