Resin Documentationapp server |
logging
Resin can perform access logging, specify where JDK logging interface messages go, and redirect the stderr and stdout for your applications. OverviewResin uses the JDK standard java.util.logging for all its internal logging and offers flexible configuration for the logging format and the logging level. The logging configuration has two parts: the set of log handlers, and the logger level. A log handler tells Resin where to send logging output. Resin includes file-based log handlers, mail handlers, syslog handlers, and any custom logging handler following the JDK standard. The log handler is configured with a name and a level which must both match for the log to be output. <resin xmlns="http://caucho.com/ns/resin"> <log-handler name="com.foo" level="all" path="${resin.root}/log/foo.log" timestamp="[%y-%m-%d %H:%M:%S.%s] {%{thread}} "/> ... </resin> The <logger> configures the logging level for a named logger. Because a <logger> will generally have several log-handlers, both the logger level and the log-handler level must match for the log to output. Since the logger and log-handler names are hierarchical, a "com.foo" <logger> will enable "com.foo.bar". <resin xmlns="http://caucho.com/ns/resin"> <logger name="com.foo" level="fine"/> <logger name="com.foo.bar" level="finest"/> ... </resin> Log namesThe JDK logging api uses a hierarchical naming scheme. Typically the name
is aligned with a java class name. When you specify a name, all logging
requests that use a name that starts with the name you have specified are
matched. For example: Resin's own logging is based on Resin's source class names. The following are useful log names in Resin:
Log levelsThe logger enables logs for a given debugging granularity. A "severe" level only shows logs which threaten the stability of the server, and a "fine" level shows debugging information intended for application/library users.
The logger levels match the values defined by
the JDK
<log-handler>Configure a log handler for the JDK In addition to configuring custom handlers, <log-handler> has the most common configuration built-in: logging to a rotating file. Most of the configuration attributes are used for the rotating file and are shared with the other logging configuration. log-handler timestampThe for log tags is a format string which can contain percent codes which are substituted with time and date values.
<resin xmlns="http://caucho.com/ns/resin"> <log-handler name='' path='stderr:' timestamp="[%H:%M:%S.%s] {%{thread}}"/> ... </resin> [22:50:11.648] WebApp[/doc] starting [22:50:11.698] http listening to *:8080 [22:50:11.828] hmux listening to *:6800 log-handler archivingThe following example is a standard log handler writing to a rollover file. Because the handler's level is "all", the <logger> configuration will set the actual logging level. <web-app xmlns="http://caucho.com/ns/resin"> <log-handler name="" level="all" timestamp="[%Y/%m/%d %H:%M:%S.%s] {%{thread}} "/> <logger name="com.caucho" level="info"/> </web-app> The default archive format is + ".%Y%m%d" if rollover-period >= 1 day. + ".%Y%m%d.%H" if rollover-period < 1 day. For example, to log everything to standard error use: <resin xmlns="http://caucho.com/ns/resin"> <log-handler name="" level="all" path="stderr:" timestamp="[%H:%M:%S.%s]"/> ... </resin> A useful technique is to enable full debug logging to track down a problem: <resin> ... <log-handler name="" level="finer" path="log/debug.log" timestamp="[%H:%M:%S.%s]" rollover-period="1h" rollover-count="1"/> ... </resin> log-handler EL formattingThe <log-handler name="" level="all" path="stderr:" timestamp="[%H:%M:%S.%s]" format=" ${log.level} ${log.name} ${log.message}"/>
You can also use the Environment EL variables in your format string: <host ...> <web-app> <log name='' level='all' path='log/debug.log' timestamp="[%H:%M:%S.%s]" format=" [${app.contextPath}] ${log.message}"/> ... </web-app> ... </host> [14:55:10.189] [/foo] `null' returning JNDI java: model for EnvironmentClassLoader[web-app:http://localhost:8080/foo] [14:55:10.189] [/foo] JNDI lookup `java:comp/env/caucho/auth' exception javax.naming.NameNotFoundException: java:comp/env/caucho/auth [14:55:10.199] [/foo] Application[http://localhost:8080/foo] starting The fmt.sprintf() function can space pad the values and make the results look a little nicer: <log name="" level="all" path="stderr:" timestamp="[%H:%M:%S.%s]" format=" ${fmt.sprintf('%-7s %45s %s',log.level,log.loggerName,log.message)}"> [14:28:08.137] INFO com.caucho.vfs.QJniServerSocket Loaded Socket JNI library. [14:28:08.137] INFO com.caucho.server.port.Port http listening to *:8080 [14:28:08.137] INFO com.caucho.server.resin.ServletServer ServletServer[] starting [14:28:08.307] INFO com.caucho.server.port.Port hmux listening to localhost:6802 [14:28:08.437] INFO com.caucho.server.host.Host Host[] starting fmt.sprintf() and fmt.timestamp() can be used to produce CSV files: <log name="" level="all" path="log/debug.csv" timestamp="" format="${fmt.sprintf('%vs,%d,%d,%vs,%vs',fmt.timestamp('%Y-%m-%d %H:%M:%S.%s'), log.threadID, log.level.intLevel(), log.loggerName, log.message)}"/> "2003-11-17 14:46:14.529",10,800,"com.caucho.vfs.QJniServerSocket", "Loaded Socket JNI library." "2003-11-17 14:46:14.549",10,800,"com.caucho.server.port.Port", "http listening to *:8080" "2003-11-17 14:46:14.549",10,800,"com.caucho.server.resin.ServletServer", "ServletServer[] starting" "2003-11-17 14:46:14.719",10,800,"com.caucho.server.port.Port", "hmux listening to localhost:6802" "2003-11-17 14:46:14.850",10,800,"com.caucho.server.host.Host", "Host[] starting" "2003-11-17 14:46:15.100",10,800,"com.caucho.server.webapp.Application", "Application[http://localhost:8080/freelistbm] starting" Logger: Application loggingYou can take advantage of the JDK's logging facility to add logging to your application. Choosing a good logging name and levels are important for troubleshooting and debugging your code. Logging to much can be almost as confusing as logging too little. The logging name should be the full class name of the class you're instrumenting. Although other schemes are possible, the class name is more maintainable. The logging level should be consistent across your application. For Resin, we use the following level conventions: import java.util.logging.Logger; import java.util.logging.Level; public class Foo { private static final Logger log = Logger.getLogger(Foo.class.getName()); ... void doFoo(String bar) { // check for log level if your logging call does anything more // than pass parameters if (log.isLoggable(Level.FINER)) log.finer(this + "doFoo(" + bar + ")"); ... log.info(...); try { ... } catch (ExpectedException ex) { log.log(Level.FINEST, "expected exception", ex); } } ... } Custom and library log handlersCustom handlers and log handlers from libraries can be configured with Resin's logging system, using the CanDI XML configuration syntax. The custom handler is a child of <log-handler> and configured with any argument or setters necessary. Resin will install the handler just like one of its own handlers. <web-app xmlns="http://caucho.com/ns/resin" xmlns:jdk-logging="urn:java.util.logging"> <log-handler name="com.foo" level="info"> <jdk-logging:FileHandler> <new> <value>/tmp/test.out</value> </new> </jdk-logging:FileHandler> </logger> </web-app> package com.foo.demo; import java.util.logging.*; public class MyHandler extends Handler { @Override public void publish(LogRecord record) { System.out.println(getFormatter().format(record)); } @Override public void flush(); { } @Override public void close(); { } } Custom log formattingThe formatting of a log message can be customized just like the log handler. The Formatter is a java.util.logging interface which Resin's logging understands and can be configured with <log-handler>. Sites may wish to change the formatting of log messages to gather information more appropriate for the site. The formatter can be custom-configured just like the handlers. <web-app xmlns="http://caucho.com/ns/resin" xmlns:mypkg="urn:java:com.mycom.mypkg"> <log-handler name="com.foo" level="warning" path="WEB-INF/log.log"> <formatter><mypkg:MyFormatter/></formatter> </log-handler> </web-app> package com.mycom.mypkg; import java.util.logging.*; public class MyFormatter extends Formatter { @Override public String format(LogRecord record) { return "[" + record.getLevel() + "] " + record.getMessage(); } } Resin Builtin Log HandlersResin provides a number of predefined custom log handlers for common logging patterns, including sending messages to JMS, HMTP, and the syslog service. Creating your own custom handler is also straightforward. BamLogHandler (4.0.5)The BAM handler publishes the log message to a BAM
agent. The agent can be a custom HMTP service to process log messages.
The <web-app xmlns="http://caucho.com/ns/resin" xmlns:resin="urn:java:com.caucho.resin"> <logger name="com.foo"> <resin:BamLogHandler level="warning"> <to>test@localhost</to> </resin:BamLogHandler> </logger> </web-app> EventLogHandlerThe event handler publishes a <web-app xmlns="http://caucho.com/ns/resin" xmlns:resin="urn:java:com.caucho.resin"> <logger name="com.foo"> <resin:EventHandler level="warning"/> </logger> </web-app> JmsLogHandlerThe JMS handler publishes the log message to a JMS queue. <web-app xmlns="http://caucho.com/ns/resin" xmlns:ee="urn:java:ee" xmlns:resin="urn:java:com.caucho.resin"> <resin:MemoryQueue ee:Named="myQueue"/> <logger name="com.foo"> <resin:JmsLogHandler level="warning"> <target>${myQueue}</target> </resin:JmsLogHandler> </logger> </web-app> MailLogHandler (4.0.5+)The Mail handler sends log messages to an email address. To keep the number of mails down, the handler will concatenate messages and only send them after a period of time.
<web-app xmlns="http://caucho.com/ns/resin" xmlns:resin="urn:java:com.caucho.resin"> <logger name=""> <resin:MailLogHandler level="warning"> <to>admin@foo.com</to> <properties> mail.smtp.host=127.0.0.1 mail.smtp.port=25 </properties> </resin:MailLogHandler> </logger> </web-app> SyslogHandlerOn Unix systems, the SyslogHandler lets you log messages to syslog. <resin xmlns="http://caucho.com/ns/resin" xmlns:resin="urn:java:com.caucho.resin"> <logger name=""> <resin:SyslogHandler level="warning"> <facility>daemon</facility> <severity>notice</severity> </resin:SyslogHandler> </logger> </resin> The possible values for The possible values for See also ` Log rotation are a way stop your log files from getting too large, and to archive log files on a weekly or daily basis. When a rollover is triggered, the existing log file is renamed and a new file is started. Logs can be rotated by size or by time. The same log rotation mechanism in Resin is used for JDK logging, HTTP access logging, and standard output logging. Size based rolloverA size based rollover is triggered when the size of the file reaches a certain amount. The default Resin behaviour for log's is to rollover when the file size reaches 1mb.
Time based rolloverA time based rollover is triggered when a certain period of time has passed since the last rollover. The default Resin behaviour is to perform no time based rollover, unless rollover-size has been disabled with a value of -1 in which case the default time period is 1 month.
Archive filesWhen a rollover is triggered, the log file is renamed (archived) and a new log file is started.
The default behaviour depends on the value of rollover-period. If
rollover-period is greater than one day, or is not being used because
rollover-size has been specified, the archive filename is the original path
with Disabling rolloversTo completely disable rollovers, set the <stdout-log path="log//stdout.log" rollover-size="1024mb"/> CompressionRollover log files can be compressed with gzip or zip. The extension of the archive-format determines the compression. <log name="" level="warning" path='log/error.log' archive-format="%Y-%m-%d.error.log.gz" rollover-period="1D"/> <access-log path="log/access.log" archive-format="access-%Y%m%d.log.gz" rollover-period="1D"/> Configure the destination for .Usage of the -stdout . If it is, there will be conflicts with
which process owns the file.
The default archive format is + ".%Y%m%d" or + ".%Y%m%d.%H" if rollover-period < 1 day. The following example configures <host>. Unless a <web-app> overrides
with it's own ... <host id='foo.com'> <stdout-log path='/var/log/foo/stdout.log' rollover-period='1W'/> ... </host> ... Configure the destination for .Usage of the -stderr . If it is, there will be conflicts with
which process owns the file.
The default archive format is + ".%Y%m%d" or + ".%Y%m%d.%H" if rollover-period < 1 day. The following example configures <host>. Unless a <web-app> overrides
with it's own ... <host id='foo.com'> <stderr-log path='/var/log/foo/stderr.log' rollover-period='1W'/> ... </host> ... child of <cluster>,<cluster-default>,<server>,<server-default>,<host>,<host-default>,<web-app>,<web-app-default>
<access-log> configures the access log file. As a child of <web-app>, overrides the definition in the <host> that the web-app is deployed in. As a child of <host>, overrides the definition in the <server> that the host is in. The default archive format is + ".%Y%m%d" or + ".%Y%m%d.%H" if rollover-period < 1 day. The access log formatting variables follow the Apache variables:
The default format is: "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" com.caucho.http.log.AccessLog. Resin-IoC initialization can be used to set bean parameters in the custom class. allows for custom logging. Applications can extend a custom class from
element access-log { path? & path-format? & archive-format? $amp;auto-flush? & auto-flush-time? & exclude* & format? & hostname-dns-lookup? & rollover-period? & rollover-size? & rollover-count? & resin:type? & init? } <resin xmlns="http://caucho.com/ns/resin"> <cluster id="app-tier"> <host id=""> <access-log path='log/access.log'> <rollover-period>2W</rollover-period> </access-log> </host> </cluster> </resin> <resin xmlns="http://caucho.com/ns/resin"> <cluster id="app-tier"> <host id='foo.com'> <access-log> <test:MyLog xmlns:test="urn:java:test"> path='${resin.root}/foo/error.log' rollover-period='1W'> <test:foo>bar</test:foo> </test:MyLog> </access-log> ... </host> </cluster> </resin> <access-log>, <stdout-log>, and <stderr-log> are configured
to go to files, and
<log name="" level="all" path="stdout:"/> You can use the Environment EL variables as part of your filesystem path: <log name="" level="all" path="log/debug-${server.id}.log" rollover-period="1h" rollover-count="1"/> If you need to create a custom access log, you can create your own implementation extending com.caucho.http.log.AccessLog and configuring it. ... <host-default> <access-log> <mypkg:MyCustomLog xmlns:mypkg="urn:java:com.mypkg"/> </access-log> </host-default> package com.mypkg; import java.io.*; import javax.servlet.*; import javax.servlet.http.*; import com.caucho.http.log.*; public class MyLog extends AccessLog { public void log(HttpServletRequest req, HttpServletResponse res, ServletContext application) { System.out.println.add(req.getRequestURI()); } }
|