Project

General

Profile

Logging Configuration

See also Logging Infrastructure and Logging.

Whether you are investigating an issue in FWD runtime code or in business logic, a well-placed logging statement can be a low impact mechanism to look inside the state of your application or the runtime environment. Logging statements should be added with careful consideration for performance impacts and readability of the resulting log information.

In the FWD environment a logging infrastructure based on the J2SE logging environment is available to the developer.

Logging Facility

The foundation of logging in the FWD environment is based on the logging infrastructure added to the Java platform in J2SE 1.4, the public API for which is in the java.util.logging package. FWD takes advantage more specifically of the following components:
  • java.util.logging.Level
  • java.util.logging.FileHandler

The core of the logging in FWD is CentralLogger class, instances of which are worker objects used to log messages for specific system or application components. Loggers are named using a dot-separated, hierarchical namespace, which typically corresponds with a specific package or class name. This is the convention followed in FWD.

Log messages are each assigned a level of severity which are constants of the Level class. The following mappings are used to convert a symbolic string in the directory (the server's primary configuration file) into a Level constant. This table is in order of least verbose logging to most verbose logging:

Configuration Value Logging Level Semantics
OFF Level.OFF Logging disabled
SEVERE Level.SEVERE Critical exception
WARNING Level.WARNING Important issue
INFO Level.INFO Important message
FINE Level.CONFIG Configuration details
FINE Level.FINE Debug message
FINER Level.FINER Debug/trace message
FINEST Level.FINEST Trace message
ALL Level.ALL Lowest level

These are checked against configuration values associated in the FWD directory with the names of individual CentralLogger instances or against default global settings. This check determines whether a given log message is recorded/displayed or not.

Configuration Resolution Algorithm

FWD can lookup settings from the storage using a Unix - filesystem like path strings. A key resembles to leaf/file in the xml structure of the directory file. There are two cases:

  • if the value is a fixed path from the root of the directory then it is an absolute path and there is no search process, the value is looked-up directly
  • any other string that can be located in different root paths is a relative path which can be searched using the algorithm briefly described in the following paragraphs.

The directory will usually contain at least one "logging" section, however the defaults set below will take effect if there is no such section. The configuration is normally found via the path /server/default/logging and in that case it defines the default values for all servers. A given server can have a more specific or custom logging configuration by adding the section via the path /server/[serverid]/logging where [serverid] is the unique server account name for the server being configured. The search algorithm described “Directory” chapter is responsible to look for the appropriate value:

  • the server-specific path is searched first and if found it is honored,
  • otherwise the default path is searched and honored if found,
  • if no logging configuration is found at all, the defaults will be used.
Log file path, rotation count and limit configs resolved by the above algorithm can be overwritten by the client:
  • for batch/gui/chui started via ClientDriver with the client bootstrap file or passed in as arguments command line,
  • for web/appserver in directory either with runtime/{account}/logging, or with clientConfig/cfgOverrides.

Example

The following is an example of how the default logging settings will be represented in directory.xml. None of this has to be explicitly configured if there is no need to change it.

 <node class="container" name="">
    <node class="container" name="server">
      <node class="container" name="default">
        <node class="container" name="logging">
          <node class="boolean" name="serverSide">
            <node-attribute name="value" value="FALSE"/>
          </node>
          <node class="container" name="file">
            <node class="string" name="path">
              <node-attribute name="value" value="fwd_%m_%tY-%tm-%td_%tH-%tM-%tS_%uos_%pid_%uf_%as_%g.log"/>
            </node>
            <node class="integer" name="rotationLimit">
              <node-attribute name="value" value="500000"/>
            </node>
            <node class="integer" name="rotationCount">
              <node-attribute name="value" value="100"/>
            </node>
          </node>
          <node class="container" name="loggers">
            <node class="string" name="root">
              <node-attribute name="value" value="INFO"/>
            </node>
            <node class="string" name="spawner">
              <node-attribute name="value" value="SEVERE"/>
            </node>
          </node>
        </node>
      </node>
    </node>
  </node>

Logging configs can be defined per account in directory.xml (appserver can be configured this way):

    <node class="container" name="server">
      <node class="container" name="default">
        <node class="container" name="runtime">
          <node class="container" name="bogus">
            <node class="container" name="logging">
              <node class="container" name="file">
                <node class="string" name="path">
                  <node-attribute name="value" value="bogus_%g.log"/>
                </node>
              </node>
            </node>
          </node>
        </node>
      </node>
    </node>

For gui/chui/batch clients bootstrap overwrites in bootstrap configs client.xml:

<node type="client">
   <client>
      <logging path="fwd_client_%tY-%tm-%td_%tH-%tM-%tS_%uos_%pid_%uf_%g.log" rotationLimit="500000" rotationCount="120" />
   </client>
</node>

Web clients config overrides work in directory.xml:

  <node class="container" name="">
    <node class="container" name="server">
      <node class="container" name="default">
        <node class="container" name="clientConfig">
          <node class="string" name="cfgOverrides">
                <node-attribute name="value" value="client:logging:path=/path/file.log client:logging:rotationLimit=500000 client:logging:rotationCount=120"/>
          </node>
        </node>
      </node>
    </node>
  </node>

Reference

The following options can be specified:

Option ID Data Type Default Value Required Details
file/path string fwd_%m_%tY-%tm-%td_%tH-%tM-%tS_%uos_%pid_%uf_%as_%g.log No The file path as pattern. By default it's used by both server and client processes, so unique placeholders/specifiers are required. Supports custom placeholders and Java formatting specifiers. See below. The value can be absolute or relative path. Absolute paths are resolved on the host so make sure they work for client hosts as well. Relative paths are relative to the launch process dir, where server or client driver is started. When logging/serverSide is TRUE relative paths are resolved only relative to the server launch dir. If the path doesn't exist, the process will try to create it, so dynamic folders can be used, e.g. based on date %tY/%tm/%td/fwd_%m_%pid_%g.log.
file/rotationLimit integer 500000 No Maximum file size for each log file in bytes for the file handler. By default on reaching ~500 kilobytes the log file gets rotated. The minimum is 500000 similar to OE.
file/rotationCount integer 120 No Number of log file generations for the file handler. Keeping the number high will make sure no logs are overwritten. Take disk space limitation and root logger level into consideration when configuring.
loggers/<logger_name> string loggers/root=INFO, loggers/spawner=WARNING No The logging level for any arbitrary logger name (in a hierarchical namespace). This sets the level for the source of a log message. That means that the class that is logging will only log messages at that level (and all less verbose levels). By convention, the namespace is based on the package/class name hierarchy. This is not required since any arbitrary text can be inserted. However, FWD does use the package and optionally the class name when creating loggers. If these loggers have a name that begins with at least one of the specified logging levels in this section, the most specific (longest) matching name will specify the logging level for that logger. There may be any number of these entries. As a result, one may specify the logging level for a specific package (and by default all contained classes and sub-packages and their classes). In addition, a more specific class or package name will override the "parent" logging level with the one specified in that more specific entry.
serverSide boolean FALSE No Determines if client processes create log files on the server or on the client side. By default client processes create log files themselves on the client side.
console boolean FALSE No DEV ENV ONLY. Outputs all logs to stderr in addition to the file.
Custom placeholders
  • %pid - process id (for server and clients);
  • %uf - FWD user (for clients);
  • %uos - OS user (for clients);
  • %as - appserver name (for clients);
  • %m - mode (for server and clients);

Supports complete java.util.logging.FileHandler specifiers:

A pattern consists of a string that includes the following special components that will be replaced at runtime:

    "/" the local pathname separator
    "%t" the system temporary directory
    "%h" the value of the "user.home" system property
    "%g" the generation number to distinguish rotated logs
    "%u" a unique number to resolve conflicts
    "%%" translates to a single percent sign "%" 

The sequence number for rotation is specified by %g. A limitation of java.util.logging.FileHandler is that it cannot be formatted.

Supports java.util.Formatter date/time specifiers (see the example in the default config):

 The following date and time conversion suffix characters are defined for the 't' conversion. The types are similar to but not completely identical to those defined by GNU date and POSIX strftime(3c).

The following conversion characters are used for formatting times:
'H'     Hour of the day for the 24-hour clock, formatted as two digits with a leading zero as necessary i.e. 00 - 23.
'I'     Hour for the 12-hour clock, formatted as two digits with a leading zero as necessary, i.e. 01 - 12.
'k'     Hour of the day for the 24-hour clock, i.e. 0 - 23.
'l'     Hour for the 12-hour clock, i.e. 1 - 12.
'M'     Minute within the hour formatted as two digits with a leading zero as necessary, i.e. 00 - 59.
'S'     Seconds within the minute, formatted as two digits with a leading zero as necessary, i.e. 00 - 60 ("60" is a special value required to support leap seconds).
'L'     Millisecond within the second formatted as three digits with leading zeros as necessary, i.e. 000 - 999.
'N'     Nanosecond within the second, formatted as nine digits with leading zeros as necessary, i.e. 000000000 - 999999999.
'p'     Locale-specific morning or afternoon marker in lower case, e.g."am" or "pm". Use of the conversion prefix 'T' forces this output to upper case.
'z'     RFC 822 style numeric time zone offset from GMT, e.g. -0800. This value will be adjusted as necessary for Daylight Saving Time. For long, Long, and Date the time zone used is the default time zone for this instance of the Java virtual machine.
'Z'     A string representing the abbreviation for the time zone. This value will be adjusted as necessary for Daylight Saving Time. For long, Long, and Date the time zone used is the default time zone for this instance of the Java virtual machine. The Formatter's locale will supersede the locale of the argument (if any).
's'     Seconds since the beginning of the epoch starting at 1 January 1970 00:00:00 UTC, i.e. Long.MIN_VALUE/1000 to Long.MAX_VALUE/1000.
'Q'     Milliseconds since the beginning of the epoch starting at 1 January 1970 00:00:00 UTC, i.e. Long.MIN_VALUE to Long.MAX_VALUE.

The following conversion characters are used for formatting dates:
'B'     Locale-specific full month name, e.g. "January", "February".
'b'     Locale-specific abbreviated month name, e.g. "Jan", "Feb".
'h'     Same as 'b'.
'A'     Locale-specific full name of the day of the week, e.g. "Sunday", "Monday" 
'a'     Locale-specific short name of the day of the week, e.g. "Sun", "Mon" 
'C'     Four-digit year divided by 100, formatted as two digits with leading zero as necessary, i.e. 00 - 99
'Y'     Year, formatted as at least four digits with leading zeros as necessary, e.g. 0092 equals 92 CE for the Gregorian calendar.
'y'     Last two digits of the year, formatted with leading zeros as necessary, i.e. 00 - 99.
'j'     Day of year, formatted as three digits with leading zeros as necessary, e.g. 001 - 366 for the Gregorian calendar.
'm'     Month, formatted as two digits with leading zeros as necessary, i.e. 01 - 13.
'd'     Day of month, formatted as two digits with leading zeros as necessary, i.e. 01 - 31
'e'     Day of month, formatted as two digits, i.e. 1 - 31.

Any characters not explicitly defined as date/time conversion suffixes are illegal and are reserved for future extensions. 

Useful General Purpose Logging

When all else fails, logging can be a useful fall-back plan. The reason one doesn't usually start with logging is that the output from logging can be quite voluminous and thus very time consuming to interpret.

Please see the section above on the logging facilities built into the runtime. These facilities would be used to configure each server's logging settings. After changing any of the directory configuration for logging, the server will need to be restarted for those settings to take effect.

The following classes have highly useful, general purpose logging implemented:

Class Best Logging Level Output
com.goldencode.p2j.util.TransactionManager FINE This will provide a log entry on every block related event and the block's current state at the time of the event. Events include entering a block, iterating a block, retrying a block and exiting a block.
com.goldencode.net.RemoteObject FINER Provides a log entry for every outbound remote call.
com.goldencode.net.RemoteObject FINEST In addition to the output from FINER level (see above), this provides a dump of the remote call parameters and a log entry (including the elapsed time) for when the remote call completes.
com.goldencode.net.Dispatcher FINER Provides a log entry for every inbound remote call.
com.goldencode.net.Dispatcher FINEST In addition to the output from FINER level (see above), this provides a dump of the remote call parameters and a log entry (including the elapsed time) for when the call completes.

Since the FWD remote object protocol is bi-directional (the client can call the server and the server can call the client), it is usually important to implement RemoteObject logging (to see outbound calls) in conjunction with Dispatcher logging (to see inbound calls). The combination allows the developer to see all protocol traffic.

Changing Logging Levels

Currently, there is no support for dynamic changes to the logging levels of individual loggers, nor to the default logging settings for the FWD server as a whole. In order to change logger settings today, the server must be stopped, the logging configuration changed in the FWD server directory, and the server must then be restarted.

This limitation may be removed in a future version of the FWD Project.


© 2004-2023 Golden Code Development Corporation. ALL RIGHTS RESERVED.