IBM would like to open a discussion within the Jakarta commons community
on evolving the Jakarta Commons Logging (JCL) API's to support Enterprise
level logging functionality. We recognize the value that a "logging
implementation independent API" brings to open source component
development, and would like to work with the community to accomplish this
goal.
We present a set of requirements as a baseline for the discussion, a
proposal for meeting these requirements, a number of points of discussion,
and attached are two Java source files that correspond to the discussion
below.
Requirements:
We recognize that the community has an overriding
requirement:
A.1. Evolution: maintain compatibility with the
current LogFactory/Log interfaces.
We have ONE primary requirement:
A.2. Globalization
Having opened the door, we'd also like to propose a few
other requirements:
B.1. Functional alignment with JSR-47 concepts.
B.2. Fix fragile configuration problems - Currently
the user has NO idea which impl is in effect.
All the default/fall back behavior means that in
the end we have an apparent non-deterministic
logging implementation. Errors in config file
names, classpath errors, classpath ordering,
etc., can all change the behavior... with no
idea which is in effect.
The fundamental problem with the current factory
is that it is dependent on "passively"
identifying a logging implementation.
We propose one solution below, but would ask a
more general question: any new bright ideas?
Proposals:
A.1. Evolution: Maintain compatibility with the
current LogFactory/Log interfaces BY PROVIDING
- Drop-in replacement of commons-logging.jar
version 1.x with a version 2.x variant.
- EnterpriseLogFactory class that extends the
existing LogFactory.
- EnterpriseLog interface that extends the
existing Log interface.
A.2. Globalization. For the enterprise logging we
need globalized messages (translated) for message
level logging API's: info, warn, error, fatal.
The remaining logging API's are considered trace
level logging API's, and do not require message
translation.
- For message level logging, support globalized
variants on the new EnterpriseLog interface:
info(Class callingClass,
String methodName,
String messageID);
info(Class callingClass,
String methodName,
String messageID,
Object messageParam);
info(Class callingClass,
String methodName,
String messageID,
Object[] messageParams);
same for warn, error, fatal.
- Utility function to support formatting for
other purposes (exception strings):
formatMessage(String messageID);
formatMessage(String messageID, Object messageParam);
formatMessage(String messageID, Object[] messageParams);
Ensure that component has an assurance that the
message will be translated/formatted as expected:
- ALL message translation must be done using
the standard java.util.ResourceBundle class,
or functional equivalent.
- ALL message formatting must be done using
the standard java.text.MessageFormat class,
or functional equivalent.
- Bind a ResourceBundleName to an EnterpriseLog
instance.
- Expects that the named ResourceBundle is
available to the logger.
B.1. Functional alignment with JSR-47 concepts.
JSR-47 has 3 trace levels: FINE, FINER, FINEST
JCL has 2 trace levels defined today: debug,
trace which corresponds to JSR-47 FINE and
FINEST in the current implementation.
The JSR-47 FINER level has no corresponding APIs
in JCL. The expectation is that the FINER level
be used for "class/method level flow".
We propose a set of API's that would correspond
to the JSR-47 FINER LEVEL, but more generally
support the "class/method level flow" logging.
- enter(Class clazz, String methodName,
Object message);
- enter(Class clazz, String methodName,
Object methodArg,
Object message)
- enter(Class clazz, String methodName,
Object[] methodArgs,
Object message);
- exit(Class clazz, String methodName,
Object result,
Object message);
- exit(Class clazz, String methodName,
Throwable exception,
Object message);
These being "new" API's, it is reasonable to have
'Log' level behavior... updating Log or only
supporting in EnterpriseLog might be an interesting
discussion point.
The JCL debug level is described (in the user's
guide) as appropriate for "detailed information
on the flow through the system." As a best
practice, would like to suggest that this be
for "component level flow", i.e. crossing
component boundries. This being a guideline,
we see no conflict with current usage.
This is in-line with current JSR-47 expectations.
This does raise a question: would a set of
API's to support this notion be appropriate?
Something along the order of:
- enterComponent(String componentName,
Class clazz,
String methodName,
...);
- etc.
B.2. Fix fragile configuration problems.
This area is more discussion, and less is
currently represented in any proposed
interface/class changes.
Two things can/should be done here:
a. tighten the 'discovery' process to minimize
"non-deterministic behavior".
b. give *serious* consideration to how we
package commons logging.
- Declarative Configuration:
Now, regarding 'fragile' configurations, a
declarative configuration driven programmatically
by the "target framework" into which a component
might be installed/executing within would resolve
a lot of the problems.
In such a solution, we should guard against
any multiplicity of such "declarations". Throw
exception, something, to if multiple occur in the
runtime.
- ONE Configuration
Even in a dynamic "discovery" process, we
should adopt a strategy of allowing only ONE
configuration to exist.
- In absense of an explicit declaration, if there
is only one logger available, use it.
- In absense of an explicit declaration, if there
are multiple loadable loggers available,
then configurable preference list could be
consulted. Such a list MUST NOT be packaged with
the commons logging distributable.
- In presense of an explicit declaration, if that
is NOT available, then fall back to a default
logger (preference list or simple logger) AND
log warning/info.
- NO configuration of explicit/default loggers in
ANY resource packaged with the logger.
- Detailed diagnostics
Detailed Internal analysis and dump on
error/warning. Explain what has failed, why,
and what should be done about it. References
to a user guide would be acceptable I think.
If there is ANY ambiguity, then WARN or INFO at
a minimum.
- Improve relationship with ClassLoader hierarchies
The parent-first class loader mechanism causes
problems with in some situations. Specifically,
J2EE environments where applications attempt to
use commons logging, AND where the runtime also
supports it.
The apparent solution is both a more
deterministic discovery process for
*configuration* data, and a more flexible
config model.
More deterministic ClassLoader behavior with
respect to configuration files:
- Force adherence to the parent-first ClassLoader
precedence even if the ClassLoaders attempt
to circumvent [force deterministic behavior].
- Walk ClassLoader hierarchy from top to
bottom, discover and track WHERE resources
[config files] are available.
- Always defer to configuration found in lowest
[closest to app] classloader.
- Look for multiple copies of config resource
loaded by any *one* classloader, throw a
configuration exception or warning w/ fall-back
to consistent default behavior in such an event
OR warn and fall-back to behavior configured by
PARENT classloader.
- NO configuration file to be packed with
commons-logging.jar
Flexible config model:
- Allow PARENT config to define a *default*
attribute [such as logger] which applies to
current classloader, and as a default to any
child loader. These attributes are always
considered in order of PARENT LAST.
- Allow PARENT config to define a *must-use*
attribute [such as logger] which forces
behavior of child loaders. These attributes
are always considered in order of PARENT FIRST,
and override a corresponding *default*
attribute.
- The distinction between *default* and
*must-use* to be made by different attribute
names.
- Repackaging
Separate Interface from Implementations. Yes,
this means TWO jar files (default). We
might produce "utility" jar files that contain
an interface with ONE implementation, and config
for that implementation. We MUST eliminate
packaging/solutions that dynamically adapt to
environments were our users loose control of
what the logger is doing.
- Misc - is there any value in:
Being able to query the logger implementation
for it's "name"?
An "Assert" the application/framework runtime
can use to verify that all is as expected?
Would be be better to "name" a logger, or
a specific configuration? I think naming a
configuration would lend better towards
a deterministic behavior.
****************************************
EnterpriseLogFactory.java:
****************************************
EnterpriseLog.java:
*******************************************
Richard A. Sitze
IBM WebSphere WebServices Development
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]