You are viewing a plain text version of this content. The canonical link for it is here.
Posted to general@logging.apache.org by sd...@apache.org on 2010/04/07 06:40:36 UTC

svn commit: r931433 - in /logging/chainsaw/trunk/src/main: java/org/apache/log4j/chainsaw/ java/org/apache/log4j/chainsaw/color/ resources/org/apache/log4j/chainsaw/help/

Author: sdeboy
Date: Wed Apr  7 04:40:36 2010
New Revision: 931433

URL: http://svn.apache.org/viewvc?rev=931433&view=rev
Log:
New feature: default color rules

 - Added default color rule support (ability to assign a tab's color rules as the default color rules for new tabs).  Default color rules can be applied to pre-existing tabs via the 'apply a tabs colors' drop down box in the color rule dialog.
 - reamed file, save as menu item to file, save displayed events as, to clarify what is being saved (the currently displayed/filtered events)
 - fixed a thumbnail bug (row index issue exposed when cyclic buffering was enabled)

Modified:
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawConstants.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawCyclicBufferTableModel.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/FileSaveAction.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanel.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogUI.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/color/ColorPanel.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/color/RuleColorizer.java
    logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/help/release-notes.html

Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawConstants.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawConstants.java?rev=931433&r1=931432&r2=931433&view=diff
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawConstants.java (original)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawConstants.java Wed Apr  7 04:40:36 2010
@@ -31,6 +31,7 @@ import java.net.URL;
 public class ChainsawConstants {
   private ChainsawConstants(){}
   
+  public static final String DEFAULT_COLOR_RULE_NAME = "Default";
   public static final Color COLOR_DEFAULT_BACKGROUND = new Color(255,255,255);
   public static final Color COLOR_DEFAULT_FOREGROUND = Color.BLACK;
 

Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawCyclicBufferTableModel.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawCyclicBufferTableModel.java?rev=931433&r1=931432&r2=931433&view=diff
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawCyclicBufferTableModel.java (original)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawCyclicBufferTableModel.java Wed Apr  7 04:40:36 2010
@@ -586,12 +586,13 @@ class ChainsawCyclicBufferTableModel ext
           fireTableRowsInserted(begin, end);
         } else {
           //we did loop - insert and then update rows
-          fireTableRowsInserted(begin, cyclicBufferSize);
-          fireTableRowsUpdated(0, cyclicBufferSize);
+          //rows are zero-indexed, subtract 1 from cyclicbuffersize for the event notification
+          fireTableRowsInserted(begin, cyclicBufferSize - 1);
+          fireTableRowsUpdated(0, cyclicBufferSize - 1);
           reachedCapacity = true;
         }
       } else {
-        fireTableRowsUpdated(0, cyclicBufferSize);
+        fireTableRowsUpdated(0, cyclicBufferSize - 1);
       }
     } else {
       fireTableRowsInserted(begin, end);

Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/FileSaveAction.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/FileSaveAction.java?rev=931433&r1=931432&r2=931433&view=diff
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/FileSaveAction.java (original)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/FileSaveAction.java Wed Apr  7 04:40:36 2010
@@ -63,7 +63,7 @@ class FileSaveAction extends AbstractAct
    *
    */
   public FileSaveAction(LogUI parent) {
-    super("Save as...");
+    super("Save displayed events as...");
 
     putValue(
       Action.ACCELERATOR_KEY,
@@ -89,7 +89,7 @@ class FileSaveAction extends AbstractAct
     }
     
     chooser.setAcceptAllFileFilterUsed(true);
-    chooser.setDialogTitle("Save Events to XML file...");
+    chooser.setDialogTitle("Save displayed events to XML file...");
     chooser.showSaveDialog(parent);
 
     File selectedFile = chooser.getSelectedFile();

Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanel.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanel.java?rev=931433&r1=931432&r2=931433&view=diff
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanel.java (original)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanel.java Wed Apr  7 04:40:36 2010
@@ -1734,18 +1734,8 @@ public class LogPanel extends DockablePa
 
     logTreePanel.ignore(preferenceModel.getHiddenLoggers());
 
-    //first attempt to load encoded file
-    File f2 =
-      new File(
-        SettingsManager.getInstance().getSettingsDirectory(), URLEncoder.encode(identifier) + COLORS_EXTENSION);
-
-    if (f2.exists()) {
-        loadColorSettings(f2);
-    } else {
-        f2 =
-            new File(
-              SettingsManager.getInstance().getSettingsDirectory(), identifier + COLORS_EXTENSION);
-    }
+    //attempt to load color settings - no need to URL encode the identifier
+    colorizer.loadColorSettings(identifier);
   }
 
   /**
@@ -1794,8 +1784,8 @@ public class LogPanel extends DockablePa
     	}
     }
 
-//    TODO colour settings need to be saved
-    saveColorSettings();
+    //no need to URL encode the identifier
+    colorizer.saveColorSettings(identifier);
   }
 
     private XStream buildXStreamForLogPanelPreference() {
@@ -2453,37 +2443,6 @@ public class LogPanel extends DockablePa
   }
 
   /**
-   * Save panel color settings
-   */
-  private void saveColorSettings() {
-    ObjectOutputStream o = null;
-
-    try {
-      File f = new File(SettingsManager.getInstance().getSettingsDirectory(), 
-      		URLEncoder.encode(getIdentifier() + COLORS_EXTENSION));
-      logger.debug("writing colors to file: " + f);
-      
-      o = new ObjectOutputStream(
-          new BufferedOutputStream(new FileOutputStream(f)));
-
-      o.writeObject(colorizer.getRules());
-      o.flush();
-    } catch (FileNotFoundException fnfe) {
-      fnfe.printStackTrace();
-    } catch (IOException ioe) {
-      ioe.printStackTrace();
-    } finally {
-      try {
-        if (o != null) {
-          o.close();
-        }
-      } catch (IOException ioe) {
-        ioe.printStackTrace();
-      }
-    }
-  }
-
-  /**
    * Load default column settings if no settings exist for this identifier
    *
    * @param event
@@ -2563,38 +2522,6 @@ public class LogPanel extends DockablePa
   }
 
   /**
-   * Load panel color settings
-   */
-  private void loadColorSettings(File f) {
-    if (f.exists()) {
-      ObjectInputStream s = null;
-
-      try {
-        s = new ObjectInputStream(
-            new BufferedInputStream(new FileInputStream(f)));
-
-        Map map = (Map) s.readObject();
-        colorizer.setRules(map);
-      } catch (EOFException eof) { //end of file - ignore..
-      }catch (IOException ioe) {
-        ioe.printStackTrace();
-        //unable to load file - delete it
-        f.delete();
-      } catch (ClassNotFoundException cnfe) {
-        cnfe.printStackTrace();
-      } finally {
-        if (s != null) {
-          try {
-            s.close();
-          } catch (IOException ioe) {
-            ioe.printStackTrace();
-          }
-        }
-      }
-    }
-  }
-
-  /**
    * Iterate over all values in the column and return the longest width
    *
    * @param index column index
@@ -3129,11 +3056,16 @@ public class LogPanel extends DockablePa
             tableModel.addTableModelListener(new TableModelListener(){
                 public void tableChanged(TableModelEvent e) {
                     int firstRow = e.getFirstRow();
-                    int lastRow = e.getLastRow();
-                    if (lastRow == Integer.MAX_VALUE) {
-                        lastRow = table.getRowCount() -1; //zero-indexed rows
+                    //lastRow may be Integer.MAX_VALUE..if so, set lastRow to rowcount - 1 (so rowcount may be negative here, which will bypass for loops below)
+                    int lastRow = Math.min(e.getLastRow(), table.getRowCount() - 1);
+                    //clear everything if we got an event w/-1 for first or last row
+                    if (firstRow < 0 || lastRow < 0) {
+                        all.clear();
+                        findMatches.clear();
                     }
 
+//                    System.out.println("lastRow: " + lastRow + ", first row: " + firstRow + ", original last row: " + e.getLastRow() + ", type: " + e.getType());
+
                     List displayedEvents = tableModel.getFilteredEvents();
                     if (e.getType() == TableModelEvent.INSERT) {
 //                        System.out.println("insert - current warnings: " + warnings.size() + ", errors: " + errors.size() + ", first row: " + firstRow + ", last row: " + lastRow);
@@ -3206,11 +3138,6 @@ public class LogPanel extends DockablePa
                                 findMatches.add(wrapper);
                             }
                         }
-                        //clear everything if we got an event w/-1
-                        if (firstRow < 0 || lastRow < 0) {
-                            all.clear();
-                            findMatches.clear();
-                        }
 //                        System.out.println("update - new warnings: " + warnings.size() + ", errors: " + errors.size());
                     }
                     invalidate();

Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogUI.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogUI.java?rev=931433&r1=931432&r2=931433&view=diff
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogUI.java (original)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogUI.java Wed Apr  7 04:40:36 2010
@@ -92,6 +92,7 @@ import org.apache.log4j.Level;
 import org.apache.log4j.LogManager;
 import org.apache.log4j.Logger;
 import org.apache.log4j.LoggerRepositoryExImpl;
+import org.apache.log4j.chainsaw.color.RuleColorizer;
 import org.apache.log4j.chainsaw.dnd.FileDnDTarget;
 import org.apache.log4j.chainsaw.help.HelpManager;
 import org.apache.log4j.chainsaw.help.Tutorial;
@@ -695,6 +696,9 @@ public class LogUI extends JFrame implem
       event.asInt(LogUI.MAIN_WINDOW_HEIGHT));
 
     getToolBarAndMenus().stateChange();
+    RuleColorizer colorizer = new RuleColorizer();
+    colorizer.loadColorSettings(ChainsawConstants.DEFAULT_COLOR_RULE_NAME);
+    allColorizers.put(ChainsawConstants.DEFAULT_COLOR_RULE_NAME, colorizer);
   }
 
   /**
@@ -709,7 +713,8 @@ public class LogUI extends JFrame implem
 
     event.saveSetting(LogUI.MAIN_WINDOW_WIDTH, getWidth());
     event.saveSetting(LogUI.MAIN_WINDOW_HEIGHT, getHeight());
-
+    RuleColorizer colorizer = (RuleColorizer) allColorizers.get(ChainsawConstants.DEFAULT_COLOR_RULE_NAME);
+    colorizer.saveColorSettings(ChainsawConstants.DEFAULT_COLOR_RULE_NAME);
   }
 
   /**

Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/color/ColorPanel.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/color/ColorPanel.java?rev=931433&r1=931432&r2=931433&view=diff
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/color/ColorPanel.java (original)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/color/ColorPanel.java Wed Apr  7 04:40:36 2010
@@ -66,6 +66,7 @@ import javax.swing.event.ListSelectionLi
 import javax.swing.table.DefaultTableModel;
 import javax.swing.table.TableCellRenderer;
 
+import org.apache.log4j.chainsaw.ChainsawConstants;
 import org.apache.log4j.chainsaw.ExpressionRuleContext;
 import org.apache.log4j.chainsaw.filter.FilterModel;
 import org.apache.log4j.chainsaw.icons.ChainsawIcons;
@@ -95,7 +96,7 @@ public class ColorPanel extends JPanel {
   private ActionListener closeListener;
   private JLabel statusBar;
   private Vector columns;
-  private final String currentTabString = "Current tab";
+  private final String noTab = "None";
   private DefaultComboBoxModel logPanelColorizersModel;
   private Map allLogPanelColorizers;
   private RuleColorizer currentLogPanelColorizer;
@@ -192,12 +193,12 @@ public class ColorPanel extends JPanel {
       loadPanelColorizersComboBox.addActionListener(new ActionListener() {
           public void actionPerformed(ActionEvent e) {
               String selectedColorizerName = loadPanelColorizersComboBox.getSelectedItem().toString();
-              copyRulesAction.setEnabled(!(currentTabString.equals(selectedColorizerName)));
+              copyRulesAction.setEnabled(!(noTab.equals(selectedColorizerName)));
           }
       });
 
     copyRulesAction.putValue(Action.NAME, "Copy color rules");
-    copyRulesAction.setEnabled(!(currentTabString.equals(loadPanelColorizersComboBox.getSelectedItem())));
+    copyRulesAction.setEnabled(!(noTab.equals(loadPanelColorizersComboBox.getSelectedItem())));
 
     JButton copyRulesButton = new JButton(copyRulesAction);
     topPanel.add(copyRulesButton);
@@ -210,8 +211,8 @@ public class ColorPanel extends JPanel {
   }
 
   public void loadLogPanelColorizers() {
-      if (logPanelColorizersModel.getIndexOf(currentTabString) == -1) {
-        logPanelColorizersModel.addElement(currentTabString);
+      if (logPanelColorizersModel.getIndexOf(noTab) == -1) {
+        logPanelColorizersModel.addElement(noTab);
       }
       for (Iterator iter = allLogPanelColorizers.entrySet().iterator();iter.hasNext();) {
           Map.Entry entry = (Map.Entry)iter.next();
@@ -371,7 +372,7 @@ public class ColorPanel extends JPanel {
     }
   }
 
-  void applyRules(String ruleSet) {
+  void applyRules(String ruleSet, RuleColorizer applyingColorizer) {
     table.getColumnModel().getColumn(0).getCellEditor().stopCellEditing();
 
     List list = new ArrayList();
@@ -414,7 +415,7 @@ public class ColorPanel extends JPanel {
       //only update rules if there were no errors
       Map map = new HashMap();
       map.put(ruleSet, list);
-      colorizer.setRules(map);
+      applyingColorizer.setRules(map);
 
     } else {
       statusBar.setText("Errors - see expression tooltip (color filters won't be active until errors are resolved)");
@@ -428,15 +429,28 @@ public class ColorPanel extends JPanel {
     panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
     panel.add(Box.createHorizontalGlue());
 
+    JButton saveAsDefaultButton = new JButton("Save as default");
+
+    saveAsDefaultButton.addActionListener(
+      new AbstractAction() {
+        public void actionPerformed(ActionEvent evt) {
+          RuleColorizer defaultColorizer = (RuleColorizer) allLogPanelColorizers.get(ChainsawConstants.DEFAULT_COLOR_RULE_NAME);
+          applyRules(currentRuleSet, defaultColorizer);
+        }
+    });
+
+    panel.add(saveAsDefaultButton);
+
     JButton applyButton = new JButton("Apply");
 
     applyButton.addActionListener(
       new AbstractAction() {
         public void actionPerformed(ActionEvent evt) {
-          applyRules(currentRuleSet);
+          applyRules(currentRuleSet, colorizer);
         }
       });
 
+    panel.add(Box.createHorizontalStrut(10));
     panel.add(applyButton);
 
     JButton closeButton = new JButton("Close");

Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/color/RuleColorizer.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/color/RuleColorizer.java?rev=931433&r1=931432&r2=931433&view=diff
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/color/RuleColorizer.java (original)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/color/RuleColorizer.java Wed Apr  7 04:40:36 2010
@@ -20,12 +20,25 @@ package org.apache.log4j.chainsaw.color;
 import java.awt.Color;
 import java.beans.PropertyChangeListener;
 import java.beans.PropertyChangeSupport;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.EOFException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.net.URLEncoder;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.log4j.chainsaw.ChainsawConstants;
+import org.apache.log4j.chainsaw.prefs.SettingsManager;
 import org.apache.log4j.rule.ColorRule;
 import org.apache.log4j.rule.ExpressionRule;
 import org.apache.log4j.rule.Rule;
@@ -48,6 +61,8 @@ public class RuleColorizer implements Co
   private Rule findRule;
   private Rule loggerRule;
 
+  private static final String COLORS_EXTENSION = ".colors";
+
   private final Color WARN_DEFAULT_COLOR = new Color(255, 255, 153);
   private final Color ERROR_OR_FATAL_DEFAULT_COLOR = new Color(255, 153, 153);
   private final Color MARKER_DEFAULT_COLOR = new Color(153, 255, 153);
@@ -209,4 +224,74 @@ public class RuleColorizer implements Co
     String propertyName, PropertyChangeListener listener) {
     colorChangeSupport.addPropertyChangeListener(propertyName, listener);
   }
+
+
+    /**
+     * Save panel color settings
+     */
+    public void saveColorSettings(String name) {
+      ObjectOutputStream o = null;
+      try {
+        File f = new File(SettingsManager.getInstance().getSettingsDirectory(), URLEncoder.encode(name + COLORS_EXTENSION));
+
+        o = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(f)));
+
+        o.writeObject(getRules());
+        o.flush();
+      } catch (FileNotFoundException fnfe) {
+        fnfe.printStackTrace();
+      } catch (IOException ioe) {
+        ioe.printStackTrace();
+      } finally {
+        try {
+          if (o != null) {
+            o.close();
+          }
+        } catch (IOException ioe) {
+          ioe.printStackTrace();
+        }
+      }
+    }
+
+  /**
+   * Load panel color settings if they exist - otherwise, load default color settings
+   */
+  public void loadColorSettings(String name) {
+    if (!doLoadColorSettings(name)) {
+      doLoadColorSettings(ChainsawConstants.DEFAULT_COLOR_RULE_NAME);
+    }
+  }
+
+  private boolean doLoadColorSettings(String name) {
+    //first attempt to load encoded file
+    File f = new File(SettingsManager.getInstance().getSettingsDirectory(), URLEncoder.encode(name) + COLORS_EXTENSION);
+
+    if (f.exists()) {
+      ObjectInputStream s = null;
+
+      try {
+        s = new ObjectInputStream(
+            new BufferedInputStream(new FileInputStream(f)));
+
+        Map map = (Map) s.readObject();
+        setRules(map);
+      } catch (EOFException eof) { //end of file - ignore..
+      }catch (IOException ioe) {
+        ioe.printStackTrace();
+        //unable to load file - delete it
+        f.delete();
+      } catch (ClassNotFoundException cnfe) {
+        cnfe.printStackTrace();
+      } finally {
+        if (s != null) {
+          try {
+            s.close();
+          } catch (IOException ioe) {
+            ioe.printStackTrace();
+          }
+        }
+      }
+    }
+    return f.exists();
+  }
 }

Modified: logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/help/release-notes.html
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/help/release-notes.html?rev=931433&r1=931432&r2=931433&view=diff
==============================================================================
--- logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/help/release-notes.html (original)
+++ logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/help/release-notes.html Wed Apr  7 04:40:36 2010
@@ -12,6 +12,7 @@
 <h1>1.99.99</h1>
 <h2>6 Apr 2010</h2>
 <ul>
+<li>Added default color rule support (ability to assign a tab's color rules as the default color rules for new tabs).  Default color rules can be applied to pre-existing tabs via the 'apply a tabs colors' drop down box in the color rule dialog.</li>
 <li>Pressing enter in the search box now initiates a search.</li>
 <li>Updated thumbnail rendering logic to display warnings, errors, fatal events and events with markers more prominently than other events.</li>
 </ul>
@@ -41,7 +42,6 @@ just creates a text file containing the 
 <li>New clickable thumbnail bar next to logpanel scroll bar provides a visual indicator of events with warning level as well as error/fatal.</li>
 <li>Clicking in the bar will jump to the closest event.</li>
 <li>Colors in the thumbnail bar will sync with the default warning and error/fatal color rules (LEVEL == WARNING) and (level == FATAL || level == ERROR) respectively.</li>
-</li>
 </ul>
 <h2>23 Mar 2010</h2>
 <ul>
@@ -351,7 +351,7 @@ not to provide this, be on the look out 
  <li>Fixed a bug in the Receivers tree panel where restarting a set of receivers would duplicate them visually.  The plugins where stopped and started, but duplicate tree nodes where being added.  Thanks to Stephen Pain for
  pointing it out. (we 'knew' about it, but we had forgotten...)</li>
  <li>Added a "Restart" action to restart an individual Receiver.</li>
- </li>Tweaked the action buttons available within the Receive toolbar to the more commonly used ones, Play/Pause still available
+ <li>Tweaked the action buttons available within the Receive toolbar to the more commonly used ones, Play/Pause still available
  from popup menu</li>
 </ul>
 
@@ -392,7 +392,7 @@ not to provide this, be on the look out 
 
 <h2>13 May 2004</h2>
 <ul>
- <li>The first version we decided we needed to have some release notes in... :)
- <li>Fix for LoggingEvent class - connecting Chainsaw v2 to a remote log4j1.2.x  caused a NullPointerException
+ <li>The first version we decided we needed to have some release notes in... :)</li>
+ <li>Fix for LoggingEvent class - connecting Chainsaw v2 to a remote log4j1.2.x  caused a NullPointerException</li>
 </ul>
 </body></html>
\ No newline at end of file