logging-log4j-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From c...@apache.org
Subject cvs commit: logging-log4j/src/java/org/apache/log4j/helpers PlatformInfo.java
Date Fri, 10 Sep 2004 14:57:24 GMT
ceki        2004/09/10 07:57:24

  Modified:    docs     HISTORY
               src/java/org/apache/log4j/spi/location LocationInfo.java
                        LegacyExtractor.java
               tests/src/java/org/apache/log4j/performance Loop.java
               src/java/org/apache/log4j/spi ThrowableInformation.java
  Added:       src/java/org/apache/log4j/helpers PlatformInfo.java
  Log:
  - Log4j will now automatically include stack traces for nested
  exceptions. Log4j extends the automatic nested exception printing
  available in JDK 1.4 to nested exceptions accessible through methods
  named "getRootCause", "getNextException" and "getException", not just
  "getCause" as in JDK 1.4. [*]
  
  - Added o.a.l.helpers.PlatformInfo utiliity class which gives information about the current
   platform properties. Some classes were modified to take advantage of the PlatformInfo class.
  
  Revision  Changes    Path
  1.112     +6 -0      logging-log4j/docs/HISTORY
  
  Index: HISTORY
  ===================================================================
  RCS file: /home/cvs/logging-log4j/docs/HISTORY,v
  retrieving revision 1.111
  retrieving revision 1.112
  diff -u -r1.111 -r1.112
  --- HISTORY	7 Sep 2004 19:06:45 -0000	1.111
  +++ HISTORY	10 Sep 2004 14:57:24 -0000	1.112
  @@ -7,6 +7,12 @@
      
      [D] Changes affect a method or property which was previously marked as 
          deprecated.
  + 
  + - Log4j will now automatically include stack traces for nested
  +   exceptions. Log4j extends the automatic nested exception printing
  +   available in JDK 1.4 to nested exceptions accessible through methods
  +   named "getRootCause", "getNextException" and "getException", not just
  +   "getCause" as in JDK 1.4. [*]
      
    - The location information extraction code has been refactored to use
      a faster mechanism when running on JDK 1.4 or later. The new mechanism, contributed

  
  
  
  1.3       +3 -11     logging-log4j/src/java/org/apache/log4j/spi/location/LocationInfo.java
  
  Index: LocationInfo.java
  ===================================================================
  RCS file: /home/cvs/logging-log4j/src/java/org/apache/log4j/spi/location/LocationInfo.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- LocationInfo.java	7 Sep 2004 18:58:42 -0000	1.2
  +++ LocationInfo.java	10 Sep 2004 14:57:24 -0000	1.3
  @@ -19,6 +19,7 @@
   package org.apache.log4j.spi.location;
   
   import org.apache.log4j.helpers.LogLog;
  +import org.apache.log4j.helpers.PlatformInfo;
   
   
   /**
  @@ -36,8 +37,6 @@
     
     static final long serialVersionUID = -1325822038990805636L;
     
  -  private static boolean haveStackTraceElement = false;
  -  
     /**
      * NA_LOCATION_INFO is used in conjunction with deserialized LoggingEvents 
      * without real location info available.
  @@ -45,14 +44,7 @@
      */
     public static LocationInfo NA_LOCATION_INFO = new LocationInfo(NA, NA, NA, NA);
    
  -  static {
  -    try {
  -      Class.forName("java.lang.StackTraceElement");
  -      haveStackTraceElement = true;
  -    } catch ( Throwable e) {
  -      // we are running on a JDK prior to 1.4
  -    } 
  -  }
  +
     
     /**
        Caller's line number.
  @@ -113,7 +105,7 @@
         return;
       }
       
  -    if(haveStackTraceElement) {
  +    if(PlatformInfo.hasStackTraceElement()) {
         StackTraceElementExtractor.extract(this, t, fqnOfCallingClass);
       } else {
         LegacyExtractor.extract(this, t, fqnOfCallingClass);  
  
  
  
  1.3       +3 -14     logging-log4j/src/java/org/apache/log4j/spi/location/LegacyExtractor.java
  
  Index: LegacyExtractor.java
  ===================================================================
  RCS file: /home/cvs/logging-log4j/src/java/org/apache/log4j/spi/location/LegacyExtractor.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- LegacyExtractor.java	7 Sep 2004 18:58:42 -0000	1.2
  +++ LegacyExtractor.java	10 Sep 2004 14:57:24 -0000	1.3
  @@ -18,7 +18,7 @@
   package org.apache.log4j.spi.location;
   
   import org.apache.log4j.Layout;
  -import org.apache.log4j.helpers.LogLog;
  +import org.apache.log4j.helpers.PlatformInfo;
   
   import java.io.PrintWriter;
   import java.io.StringWriter;
  @@ -32,18 +32,7 @@
    * @author Ceki Gülcü
    */
   public class LegacyExtractor {
  -  // Check if we are running in IBM's visual age.
  -  static boolean inVisualAge = false;
   
  -  static {
  -    try {
  -      Class dummy = Class.forName("com.ibm.uvm.tools.DebugSupport");
  -      inVisualAge = true;
  -      LogLog.debug("Detected IBM VisualAge environment.");
  -    } catch (Throwable e) {
  -      ; // nothing to do
  -    }
  -  }
   
     private static StringWriter sw = new StringWriter();
     private static PrintWriter pw = new PrintWriter(sw);
  @@ -96,7 +85,7 @@
   
       // VA has a different stack trace format which doesn't
       // need to skip the inital 'at'
  -    if (!inVisualAge) {
  +    if (!PlatformInfo.isInVisualAge()) {
         // back up to first blank character
         ibegin = s.lastIndexOf("at ", iend);
   
  @@ -164,7 +153,7 @@
         //  void test.test.Run.main(java.lang.String [])
         int ibegin = 0;
   
  -      if (inVisualAge) {
  +      if (PlatformInfo.isInVisualAge()) {
           ibegin = fullInfo.lastIndexOf(' ', iend) + 1;
         }
   
  
  
  
  1.4       +34 -17    logging-log4j/tests/src/java/org/apache/log4j/performance/Loop.java
  
  Index: Loop.java
  ===================================================================
  RCS file: /home/cvs/logging-log4j/tests/src/java/org/apache/log4j/performance/Loop.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- Loop.java	7 Sep 2004 17:16:02 -0000	1.3
  +++ Loop.java	10 Sep 2004 14:57:24 -0000	1.4
  @@ -1,12 +1,12 @@
   /*
    * Copyright 1999,2004 The Apache Software Foundation.
  - * 
  + *
    * Licensed under the Apache License, Version 2.0 (the "License");
    * you may not use this file except in compliance with the License.
    * You may obtain a copy of the License at
  - * 
  + *
    *      http://www.apache.org/licenses/LICENSE-2.0
  - * 
  + *
    * Unless required by applicable law or agreed to in writing, software
    * distributed under the License is distributed on an "AS IS" BASIS,
    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  @@ -23,19 +23,17 @@
   import org.apache.log4j.PatternLayout;
   import org.apache.log4j.joran.JoranConfigurator;
   
  +
   /**
    * Logs in a loop a number of times and measure the elapsed time.
  - * 
  + *
    * @author Ceki Gülcü
    */
   public class Loop {
  -
     static int runLength;
  -
  -  final static Logger logger = Logger.getLogger(Loop.class);
  +  static final Logger logger = Logger.getLogger(Loop.class);
   
     public static void main(String[] args) throws Exception {
  -    
       Logger j = Logger.getLogger("org.apache.log4j.joran");
       j.setAdditivity(false);
       j.setLevel(Level.WARN);
  @@ -44,31 +42,47 @@
       a.setName("console");
       a.activateOptions();
       j.addAppender(a);
  -    
  -    if (args.length == 2)
  +
  +    if (args.length == 2) {
         init(args[0], args[1]);
  -    else
  +    } else {
         usage("Wrong number of arguments.");
  +    }
   
  +    memPrint();
       loop(1000, logger, "Some fix message of medium length.");
  +    memPrint();
  +
       long res = loop(runLength, logger, "Some fix message of medium length.");
       double average = (res * 1000.0) / runLength;
  -    System.out.println("Loop completed in [" + res + "] milliseconds, or ["
  -        + average + "] microseconds per log.");
  +    System.out.println(
  +      "Loop completed in [" + res + "] milliseconds, or [" + average
  +      + "] microseconds per log.");
   
  +    memPrint();
     }
   
     static void usage(String msg) {
       System.err.println(msg);
  -    System.err.println("Usage: java " + Loop.class.getName()
  -        + " runLength configFile");
  +    System.err.println(
  +      "Usage: java " + Loop.class.getName() + " runLength configFile");
       System.err.println("\trunLength (integer) is the length of test loop.");
       System.err.println("\tconfigFile is an XML configuration file");
   
       System.exit(1);
     }
   
  -  static void init(String runLengthStr, String configFile) throws Exception {
  +  static void memPrint() {
  +    Runtime runtime = Runtime.getRuntime();
  +    long total = runtime.totalMemory();
  +    long free = runtime.freeMemory();
  +    long used = total - free;
  +    System.out.println(
  +      "Total: " + total + ", free: " + free + ", used: " + used);
  +  }
  +
  +  static void init(String runLengthStr, String configFile)
  +    throws Exception {
       runLength = Integer.parseInt(runLengthStr);
       JoranConfigurator jc = new JoranConfigurator();
       jc.doConfigure(configFile, LogManager.getLoggerRepository());
  @@ -78,7 +92,10 @@
       long before = System.currentTimeMillis();
       for (int i = 0; i < len; i++) {
         logger.debug(msg);
  +      if(i == 1000) {
  +        memPrint();
  +      }
       }
       return (System.currentTimeMillis() - before);
     }
  -}
  \ No newline at end of file
  +}
  
  
  
  1.15      +87 -49    logging-log4j/src/java/org/apache/log4j/spi/ThrowableInformation.java
  
  Index: ThrowableInformation.java
  ===================================================================
  RCS file: /home/cvs/logging-log4j/src/java/org/apache/log4j/spi/ThrowableInformation.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- ThrowableInformation.java	27 Feb 2004 16:47:34 -0000	1.14
  +++ ThrowableInformation.java	10 Sep 2004 14:57:24 -0000	1.15
  @@ -1,12 +1,12 @@
   /*
    * Copyright 1999,2004 The Apache Software Foundation.
  - * 
  + *
    * Licensed under the Apache License, Version 2.0 (the "License");
    * you may not use this file except in compliance with the License.
    * You may obtain a copy of the License at
  - * 
  + *
    *      http://www.apache.org/licenses/LICENSE-2.0
  - * 
  + *
    * Unless required by applicable law or agreed to in writing, software
    * distributed under the License is distributed on an "AS IS" BASIS,
    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  @@ -19,49 +19,87 @@
   import java.io.PrintWriter;
   import java.io.Writer;
   
  +import java.lang.reflect.Method;
  +
   import java.util.Vector;
   
  +import org.apache.log4j.helpers.PlatformInfo;
  +
   
   /**
  -  * ThrowableInformation is log4j's internal representation of
  -  * throwables. It essentially consists of a string array, called
  -  * 'rep', where the first element, that is rep[0], represents the
  -  * string representation of the throwable (i.e. the value you get
  -  * when you do throwable.toString()) and subsequent elements
  -  * correspond the stack trace with the top most entry of the stack
  -  * corresponding to the second entry of the 'rep' array that is
  -  * rep[1].
  -  * 
  -  * Note that ThrowableInformation does not store the throwable it represents. 
  -  * 
  -  * @author Ceki G&uuml;lc&uuml;
  -  *
  -  * */
  + * ThrowableInformation is log4j's internal representation of throwables. It
  + * essentially consists of a string array, called 'rep', where the first
  + * element, that is rep[0], represents the string representation of the
  + * throwable (i.e. the value you get when you do throwable.toString()) and
  + * subsequent elements correspond the stack trace with the top most entry of the
  + * stack corresponding to the second entry of the 'rep' array that is rep[1].
  + *
  + * Note that ThrowableInformation does not store the throwable it represents.
  + *
  + * @author Ceki G&uuml;lc&uuml;
  + *
  + */
   public class ThrowableInformation implements java.io.Serializable {
     static final long serialVersionUID = -4748765566864322735L;
  +
     //private transient Throwable throwable;
  -  
     private String[] rep;
   
     public ThrowableInformation(Throwable throwable) {
  -    rep = extractStringRep(throwable);
  +    VectorWriter vw = new VectorWriter();
  +    extractStringRep(throwable, vw);
  +    rep = vw.toStringArray();
     }
   
     public ThrowableInformation(String[] rep) {
       this.rep = rep;
     }
   
  - // public Throwable getThrowable() {
  -   // return throwable;
  +  // public Throwable getThrowable() {
  +  // return throwable;
     //}
   
  -  public String[] extractStringRep(Throwable throwable) {
  -    VectorWriter vw = new VectorWriter();
  -    throwable.printStackTrace(vw);
  -    String[] extractedRep = vw.toStringArray();
  -    return extractedRep;   
  +  public void extractStringRep(Throwable t, VectorWriter vw) {
  +    t.printStackTrace(vw);
  +
  +    // Check if the Throwable t has a nested Throwable. If so, invoke
  +    // extractStringRep recursively.
  +    // Note that the Throwable.getCause was added in JDK 1.4. The printStackTrace
  +    // method was modified in JDK 1.4 to handle the nested throwable returned
  +    // by Throwable.getCause.
  +    try {
  +      Class tC = t.getClass();
  +      Method[] mA = tC.getMethods();
  +      Method nextThrowableMethod = null;
  +      for (int i = 0; i < mA.length; i++) {
  +        if (("getCause".equals(mA[i].getName()) && !PlatformInfo.isJDK14OrLater())
  +            || "getRootCause".equals(mA[i].getName())
  +            || "getNextException".equals(mA[i].getName())
  +            || "getException".equals(mA[i].getName())) {
  +          // check param types
  +          Class[] params = mA[i].getParameterTypes();
  +          if ((params == null) || (params.length == 0)) {
  +            // just found the getter for the nested throwable
  +            nextThrowableMethod = mA[i];
  +            break; // no need to search further
  +          }
  +        }
  +      }
  +
  +      if (nextThrowableMethod != null) {
  +        // get the nested throwable and log it
  +        Throwable nextT =
  +          (Throwable) nextThrowableMethod.invoke(t, new Object[0]);
  +        if (nextT != null) {
  +          vw.print("Root cause follows.");
  +          extractStringRep(nextT, vw);
  +        }
  +      }
  +    } catch (Exception e) {
  +      // do nothing
  +    }
     }
  -  
  +
     /**
      * Retun a clone of the string representation of the exceptopn (throwable)
      * that this object represents.
  @@ -69,52 +107,52 @@
     public String[] getThrowableStrRep() {
       return (String[]) rep.clone();
     }
  -  
  +
     public boolean equals(Object o) {
  -    if(this == o) {
  +    if (this == o) {
         return true;
       }
  -    
  -    if(!(o instanceof ThrowableInformation)) {
  +
  +    if (!(o instanceof ThrowableInformation)) {
         return false;
       }
  -    
  +
       ThrowableInformation r = (ThrowableInformation) o;
  -    
  -    if(rep == null) {
  -      if(r.rep != null) {
  +
  +    if (rep == null) {
  +      if (r.rep != null) {
           return false;
         } else {
           return true;
         }
       }
  -    
  +
       // at this point we know that both rep and r.rep are non-null.
  -    if(rep.length != r.rep.length) {
  +    if (rep.length != r.rep.length) {
         return false;
       }
  -    
  +
       int len = rep.length;
  -    for(int i = 0; i < len; i++) {
  -      if(!rep[i].equals(r.rep[i])) {
  +    for (int i = 0; i < len; i++) {
  +      if (!rep[i].equals(r.rep[i])) {
           return false;
         }
       }
  -    
  +
       return true;
     }
   }
   
   
   /**
  -  * VectorWriter is a seemingly trivial implemtantion of PrintWriter.
  -  * The throwable instance that we are trying to represnt is asked to
  -  * print itself to a VectorWriter.
  -  *
  -  * By our design choice, r string representation of the throwable
  -  * does not contain any line separators. It follows that println()
  -  * methods of VectorWriter ignore the 'ln' part.
  -  * */
  + * VectorWriter is a seemingly trivial implemtantion of PrintWriter. The
  + * throwable instance that we are trying to represnt is asked to print itself to
  + * a VectorWriter.
  + *
  + * By our design choice, r string representation of the throwable does not
  + * contain any line separators. It follows that println() methods of
  + * VectorWriter ignore the 'ln' part.
  + */
   class VectorWriter extends PrintWriter {
     private Vector v;
   
  
  
  
  1.1                  logging-log4j/src/java/org/apache/log4j/helpers/PlatformInfo.java
  
  Index: PlatformInfo.java
  ===================================================================
  /*
   * Copyright 1999,2004 The Apache Software Foundation.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package org.apache.log4j.helpers;
  
  import java.util.Properties;
  
  
  /**
   * This class provides information about the runtime platform.
   *
   * @author Ceki Gulcu
   * @since 1.3
   * */
  public class PlatformInfo {
    private static final int UNINITIALIZED = -1;
  
    // Check if we are running in IBM's visual age.
    private static int inVisualAge = UNINITIALIZED;
    private static int onAS400 = UNINITIALIZED;
    private static int hasStackTraceElement = UNINITIALIZED;
  
    public static boolean isInVisualAge() {
      if (inVisualAge == UNINITIALIZED) {
        try {
          Class dummy = Class.forName("com.ibm.uvm.tools.DebugSupport");
          inVisualAge = 1;
        } catch (Throwable e) {
          inVisualAge = 0;
        }
      }
      return (inVisualAge == 1);
    }
  
    /**
     * Are we running on AS400?
     */
    public static boolean isOnAS400() {
      if (onAS400 == UNINITIALIZED) {
        try {
          Properties p = System.getProperties();
          String osname = p.getProperty("os.name");
          if ((osname != null) && (osname.equals("OS/400"))) {
            onAS400 = 1;
          } else {
            onAS400 = 0;
          }
        } catch (Throwable e) {
          // This should not happen, but if it does, assume we are not on
          // AS400.
          onAS400 = 0;
        }
      }
      return (onAS400 == 1);
    }
  
    public static boolean hasStackTraceElement() {
      if (hasStackTraceElement == UNINITIALIZED) {
        try {
          Class.forName("java.lang.StackTraceElement");
          hasStackTraceElement = 1;
        } catch (Throwable e) {
          // we are running on a JDK prior to 1.4
          hasStackTraceElement = 0;
        }
      }
      return (hasStackTraceElement == 1);
    }
    
    public static boolean isJDK14OrLater() {
      return hasStackTraceElement();
    }
  }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-dev-help@logging.apache.org


Mime
View raw message