Commons Logging
  1. Commons Logging
  2. LOGGING-89

[logging] Enterprise Commons Logging : Globalization & more

    Details

    • Type: Improvement Improvement
    • Status: Resolved
    • Priority: Minor Minor
    • Resolution: Won't Fix
    • Affects Version/s: None
    • Fix Version/s: None
    • Labels:
      None
    • Environment:

      Operating System: All
      Platform: All

      Description

      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?

        Issue Links

          Activity

          Hide
          Richard A. Sitze added a comment -

          Created an attachment (id=13714)
          Initial proposed EnterpriseLog.java

          Show
          Richard A. Sitze added a comment - Created an attachment (id=13714) Initial proposed EnterpriseLog.java
          Hide
          Richard A. Sitze added a comment -

          Created an attachment (id=13715)
          Initial proposed EnterpriseLogFactory.java

          Show
          Richard A. Sitze added a comment - Created an attachment (id=13715) Initial proposed EnterpriseLogFactory.java
          Hide
          Richard A. Sitze added a comment -

          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.
          Show
          Richard A. Sitze added a comment - 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.
          Hide
          Richard A. Sitze added a comment -

          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.
          Show
          Richard A. Sitze added a comment - 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.
          Hide
          Richard A. Sitze added a comment -

          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.
          Show
          Richard A. Sitze added a comment - 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.
          Hide
          Richard A. Sitze added a comment -

          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.

          Show
          Richard A. Sitze added a comment - 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.
          Hide
          Boris Unckel added a comment -

          (In reply to comment #6)
          This is already available with java.util.logging. Why is this needed for JCL?
          JCL's main intention is for use in APIs. APIs already using JCL whould have to
          be changed (major change) with rewritting all logging calls for I18N.

          New APIs (I assume JDK1.4 and above) could use java.util.logging for this
          requirement.
          There were already discussions on the log4j dev mailing list to this topic, with
          consensus to leave an stable interface.

          Show
          Boris Unckel added a comment - (In reply to comment #6) This is already available with java.util.logging. Why is this needed for JCL? JCL's main intention is for use in APIs. APIs already using JCL whould have to be changed (major change) with rewritting all logging calls for I18N. New APIs (I assume JDK1.4 and above) could use java.util.logging for this requirement. There were already discussions on the log4j dev mailing list to this topic, with consensus to leave an stable interface.
          Hide
          Thomas Neidhart added a comment -

          Considering the available alternatives (log4j, logback, slf4j) and the state of JCL, this proposal is not going to happen anymore.

          Show
          Thomas Neidhart added a comment - Considering the available alternatives (log4j, logback, slf4j) and the state of JCL, this proposal is not going to happen anymore.

            People

            • Assignee:
              Unassigned
              Reporter:
              Richard A. Sitze
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development