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/11/05 09:26:33 UTC
svn commit: r1031469 - in /logging/chainsaw/trunk/src/main:
java/org/apache/log4j/chainsaw/ resources/org/apache/log4j/chainsaw/help/
Author: sdeboy
Date: Fri Nov 5 08:26:33 2010
New Revision: 1031469
URL: http://svn.apache.org/viewvc?rev=1031469&view=rev
Log:
Added ability to create log file receiver configurations from log4j xml configuration fileappender entries
Parses the xml configuration and the patternLayout and date specifiers and creates LogFilePatternReceiver entries
Modified:
logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogFilePatternLayoutBuilder.java
logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogUI.java
logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ReceiverConfigurationPanel.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/LogFilePatternLayoutBuilder.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogFilePatternLayoutBuilder.java?rev=1031469&r1=1031468&r2=1031469&view=diff
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogFilePatternLayoutBuilder.java (original)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogFilePatternLayoutBuilder.java Fri Nov 5 08:26:33 2010
@@ -16,13 +16,23 @@
*/
package org.apache.log4j.chainsaw;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.log4j.FileAppender;
import org.apache.log4j.helpers.OptionConverter;
import org.apache.log4j.pattern.ClassNamePatternConverter;
+import org.apache.log4j.pattern.DatePatternConverter;
import org.apache.log4j.pattern.FileLocationPatternConverter;
import org.apache.log4j.pattern.FullLocationPatternConverter;
import org.apache.log4j.pattern.LevelPatternConverter;
@@ -39,6 +49,14 @@ import org.apache.log4j.pattern.Properti
import org.apache.log4j.pattern.RelativeTimePatternConverter;
import org.apache.log4j.pattern.SequenceNumberPatternConverter;
import org.apache.log4j.pattern.ThreadPatternConverter;
+import org.apache.log4j.xml.Log4jEntityResolver;
+import org.apache.log4j.xml.SAXErrorHandler;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
public class LogFilePatternLayoutBuilder
{
@@ -52,11 +70,39 @@ public class LogFilePatternLayoutBuilder
return getFormatFromConverters(converters);
}
+ public static String getTimeStampFormat(String patternLayout) {
+ int basicIndex = patternLayout.indexOf("%d");
+ if (basicIndex < 0) {
+ return null;
+ }
+
+ int index = patternLayout.indexOf("%d{");
+ //%d - default
+ if (index < 0) {
+ return "yyyy-MM-dd HH:mm:ss,SSS";
+ }
+
+ int length = patternLayout.substring(index).indexOf("}");
+ String timestampFormat = patternLayout.substring(index + "%d{".length(), index + length);
+ if (timestampFormat.equals("ABSOLUTE")) {
+ return "HH:mm:ss,SSS";
+ }
+ if (timestampFormat.equals("ISO8601")) {
+ return "yyyy-MM-dd HH:mm:ss,SSS";
+ }
+ if (timestampFormat.equals("DATE")) {
+ return "dd MMM yyyy HH:mm:ss,SSS";
+ }
+ return timestampFormat;
+ }
+
private static String getFormatFromConverters(List converters) {
StringBuffer buffer = new StringBuffer();
for (Iterator iter = converters.iterator();iter.hasNext();) {
LoggingEventPatternConverter converter = (LoggingEventPatternConverter)iter.next();
- if (converter instanceof MessagePatternConverter) {
+ if (converter instanceof DatePatternConverter) {
+ buffer.append("TIMESTAMP");
+ } else if (converter instanceof MessagePatternConverter) {
buffer.append("MESSAGE");
} else if (converter instanceof LoggerPatternConverter) {
buffer.append("LOGGER");
@@ -98,4 +144,74 @@ public class LogFilePatternLayoutBuilder
}
return buffer.toString();
}
+
+ public static Map getAppenderConfiguration(File file) throws IOException, ParserConfigurationException, SAXException {
+ InputStream stream = file.toURI().toURL().openStream();
+ Map result = new HashMap();
+ try {
+ InputSource src = new InputSource(stream);
+ src.setSystemId(file.toURI().toURL().toString());
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder docBuilder = dbf.newDocumentBuilder();
+
+ docBuilder.setErrorHandler(new SAXErrorHandler());
+ docBuilder.setEntityResolver(new Log4jEntityResolver());
+ Document doc = docBuilder.parse(src);
+ NodeList appenders = doc.getElementsByTagName("appender");
+ for (int i = 0; i < appenders.getLength(); i++) {
+ Node appender = appenders.item(i);
+ NamedNodeMap appenderAttributes = appender.getAttributes();
+// Class appenderClass = Class.forName(map.getNamedItem("class").getNodeValue());
+ Node appenderClass = appenderAttributes.getNamedItem("class");
+ try {
+ if (appenderAttributes.getNamedItem("name") != null && appenderClass != null && appenderClass.getNodeValue() != null) {
+ //load the class or try to support custom subclasses that we don't have available in the classpath but end in 'FileAppender'
+ if (appenderClass.getNodeValue().toLowerCase().endsWith("fileappender") || FileAppender.class.isAssignableFrom(Class.forName(appenderClass.getNodeValue()))) {
+ String appenderName = appenderAttributes.getNamedItem("name").getNodeValue();
+ //subclass of FileAppender - add it
+ Map entry = new HashMap();
+ NodeList appenderChildren = appender.getChildNodes();
+ for (int j = 0; j < appenderChildren.getLength(); j++) {
+ Node appenderChild = appenderChildren.item(j);
+ if (appenderChild.getNodeName().equals("param") && appenderChild.hasAttributes()) {
+ Node fileNameNode = appenderChild.getAttributes().getNamedItem("name");
+ if (fileNameNode != null && fileNameNode.getNodeValue().equals("file")) {
+ Node fileValueNode = appenderChild.getAttributes().getNamedItem("value");
+ if (fileValueNode != null) {
+ entry.put("file", fileValueNode.getNodeValue());
+ }
+ }
+ }
+ if (appenderChild.getNodeName().equals("layout") && appenderChild.hasAttributes()) {
+ NamedNodeMap layoutAttributes = appenderChild.getAttributes();
+ Node layoutNode = layoutAttributes.getNamedItem("class");
+ if (layoutNode != null && layoutNode.getNodeValue() != null && layoutNode.getNodeValue().equals("org.apache.log4j.PatternLayout")) {
+ NodeList layoutChildren = appenderChild.getChildNodes();
+ for (int k = 0; k < layoutChildren.getLength(); k++) {
+ Node layoutChild = layoutChildren.item(k);
+ if (layoutChild.getNodeName().equals("param") && layoutChild.hasAttributes()) {
+ Node layoutName = layoutChild.getAttributes().getNamedItem("name");
+ if (layoutName != null && layoutName.getNodeValue() != null && layoutName.getNodeValue().equals("ConversionPattern")) {
+ Node conversionValue = layoutChild.getAttributes().getNamedItem("value");
+ if (conversionValue != null) {
+ entry.put("conversion", conversionValue.getNodeValue());
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result.put(appenderName, entry);
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ } finally {
+ stream.close();
+ }
+ return result;
+ }
}
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=1031469&r1=1031468&r2=1031469&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 Fri Nov 5 08:26:33 2010
@@ -84,6 +84,7 @@ import javax.swing.event.ChangeListener;
import javax.swing.event.EventListenerList;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
+import javax.xml.parsers.ParserConfigurationException;
import org.apache.log4j.Appender;
import org.apache.log4j.AppenderSkeleton;
@@ -126,6 +127,7 @@ import org.apache.log4j.spi.LoggingEvent
import org.apache.log4j.spi.RepositorySelector;
import org.apache.log4j.xml.DOMConfigurator;
import org.apache.log4j.xml.XMLDecoder;
+import org.xml.sax.SAXException;
/**
@@ -1459,6 +1461,47 @@ public class LogUI extends JFrame implem
MessageCenter.getInstance().getLogger().info(
"An error occurred creating your Receiver");
}
+ } else if (receiverConfigurationPanel.getModel().isLog4jConfig()) {
+ File log4jConfigFile = receiverConfigurationPanel.getModel().getLog4jConfigFile();
+ if (log4jConfigFile != null) {
+ try {
+ Map entries = LogFilePatternLayoutBuilder.getAppenderConfiguration(log4jConfigFile);
+ for (Iterator iter = entries.entrySet().iterator();iter.hasNext();) {
+ try {
+ Map.Entry entry = (Map.Entry)iter.next();
+ String name = (String) entry.getKey();
+ Map values = (Map) entry.getValue();
+ //values: conversion, file
+ String conversionPattern = values.get("conversion").toString();
+ File file = new File(values.get("file").toString());
+ URL fileURL = file.toURI().toURL();
+ String timestampFormat = LogFilePatternLayoutBuilder.getTimeStampFormat(conversionPattern);
+ String receiverPattern = LogFilePatternLayoutBuilder.getLogFormatFromPatternLayout(conversionPattern);
+ VFSLogFilePatternReceiver fileReceiver = new VFSLogFilePatternReceiver();
+ fileReceiver.setName(name);
+ fileReceiver.setAutoReconnect(true);
+ fileReceiver.setContainer(LogUI.this);
+ fileReceiver.setAppendNonMatches(true);
+ fileReceiver.setFileURL(fileURL.toURI().toString());
+ fileReceiver.setTailing(true);
+ fileReceiver.setLogFormat(receiverPattern);
+ fileReceiver.setTimestampFormat(timestampFormat);
+ fileReceiver.setThreshold(Level.TRACE);
+ pluginRegistry.addPlugin(fileReceiver);
+ fileReceiver.activateOptions();
+ receiversPanel.updateReceiverTreeInDispatchThread();
+ } catch (URISyntaxException e1) {
+ e1.printStackTrace();
+ }
+ }
+ } catch (IOException e1) {
+ e1.printStackTrace();
+ } catch (ParserConfigurationException e1) {
+ e1.printStackTrace();
+ } catch (SAXException e1) {
+ e1.printStackTrace();
+ }
+ }
} else if (receiverConfigurationPanel.getModel().isLoadConfig()) {
configURL = receiverConfigurationPanel.getModel().getConfigToLoad();
} else if (receiverConfigurationPanel.getModel().isLogFileReceiverConfig()) {
Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ReceiverConfigurationPanel.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ReceiverConfigurationPanel.java?rev=1031469&r1=1031468&r2=1031469&view=diff
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ReceiverConfigurationPanel.java (original)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ReceiverConfigurationPanel.java Fri Nov 5 08:26:33 2010
@@ -30,6 +30,7 @@ import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.io.File;
import java.net.MalformedURLException;
+import java.net.URISyntaxException;
import java.net.URL;
import java.util.List;
@@ -74,6 +75,10 @@ class ReceiverConfigurationPanel extends
private DefaultComboBoxModel networkReceiverClassNameComboBoxModel;
private DefaultComboBoxModel networkReceiverPortComboBoxModel;
+ //log4j config receiver widgets
+ private JButton browseLog4jConfigButton;
+ private JTextField log4jConfigURLTextField;
+
//logfile receiver widgets
private JButton browseLogFileButton;
private JComboBox logFileFormatTypeComboBox;
@@ -97,6 +102,7 @@ class ReceiverConfigurationPanel extends
private JButton cancelButton;
//radiobutton widgets
+ private JRadioButton log4jConfigReceiverRadioButton;
private JRadioButton logFileReceiverRadioButton;
private JRadioButton networkReceiverRadioButton;
private JRadioButton useExistingConfigurationRadioButton;
@@ -106,6 +112,7 @@ class ReceiverConfigurationPanel extends
private final JPanel networkReceiverPanel = buildNetworkReceiverPanel();
private final JPanel logFileReceiverPanel = buildLogFileReceiverPanel();
+ private final JPanel log4jConfigReceiverPanel = buildLog4jConfigReceiverPanel();
private final JPanel useExistingConfigurationPanel = buildUseExistingConfigurationPanel();
private final JPanel dontWarnAndOKPanel = buildDontWarnAndOKPanel();
private final JPanel bottomDescriptionPanel = buildBottomDescriptionPanel();
@@ -140,6 +147,14 @@ class ReceiverConfigurationPanel extends
c.gridx = 0;
c.gridy = yPos++;
c.fill = GridBagConstraints.HORIZONTAL;
+ log4jConfigReceiverRadioButton = new JRadioButton(" Use log4j.xml fileappender configuration ");
+ buttonGroup.add(log4jConfigReceiverRadioButton);
+ add(log4jConfigReceiverRadioButton, c);
+
+ c = new GridBagConstraints();
+ c.gridx = 0;
+ c.gridy = yPos++;
+ c.fill = GridBagConstraints.HORIZONTAL;
networkReceiverRadioButton = new JRadioButton(" Receive events from the network ");
buttonGroup.add(networkReceiverRadioButton);
add(networkReceiverRadioButton, c);
@@ -185,6 +200,7 @@ class ReceiverConfigurationPanel extends
};
logFileReceiverRadioButton.addActionListener(al);
+ log4jConfigReceiverRadioButton.addActionListener(al);
networkReceiverRadioButton.addActionListener(al);
useExistingConfigurationRadioButton.addActionListener(al);
@@ -332,6 +348,52 @@ class ReceiverConfigurationPanel extends
return panel;
}
+ private JPanel buildLog4jConfigReceiverPanel() {
+ log4jConfigURLTextField = new JTextField();
+ browseLog4jConfigButton = new JButton(new AbstractAction(" Open File... ") {
+ public void actionPerformed(ActionEvent e) {
+ try {
+
+ URL url = browseConfig();
+
+ if (url != null) {
+ log4jConfigURLTextField.setText(url.toExternalForm());
+ }
+ } catch (Exception ex) {
+ logger.error(
+ "Error browsing for log4j config file", ex);
+ }
+ }
+ });
+
+ browseLog4jConfigButton.setToolTipText(
+ "Shows a File Open dialog to allow you to find a log4j configuration file");
+ JPanel panel = new JPanel(new GridBagLayout());
+ GridBagConstraints c = new GridBagConstraints();
+ c.gridx = 0;
+ c.gridy = 0;
+ c.gridwidth = 2;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = new Insets(0, 0, 5, 0);
+ panel.add(browseLog4jConfigButton, c);
+
+ c = new GridBagConstraints();
+ c.gridx = 0;
+ c.gridy = 1;
+ c.insets = new Insets(0, 5, 0, 5);
+ panel.add(new JLabel(" log4j configuration file URL "), c);
+
+ c = new GridBagConstraints();
+ c.gridx = 1;
+ c.gridy = 1;
+ c.weightx = 0.5;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ panel.add(log4jConfigURLTextField, c);
+
+
+ return panel;
+ }
+
private JPanel buildLogFileReceiverPanel() {
JPanel panel = new JPanel(new GridBagLayout());
browseLogFileButton = new JButton(new AbstractAction(" Open File... ") {
@@ -566,6 +628,9 @@ class ReceiverConfigurationPanel extends
if (component == logFileReceiverRadioButton) {
lowerPanel.add(logFileReceiverPanel, BorderLayout.NORTH);
}
+ if (component == log4jConfigReceiverRadioButton) {
+ lowerPanel.add(log4jConfigReceiverPanel, BorderLayout.NORTH);
+ }
lowerPanel.revalidate();
lowerPanel.repaint();
}
@@ -683,6 +748,10 @@ class ReceiverConfigurationPanel extends
return !cancelled && logFileReceiverRadioButton.isSelected();
}
+ boolean isLog4jConfig() {
+ return !cancelled && log4jConfigReceiverRadioButton.isSelected();
+ }
+
URL getConfigToLoad() {
try
@@ -767,5 +836,17 @@ class ReceiverConfigurationPanel extends
public boolean isCancelled() {
return cancelled;
}
+
+ public File getLog4jConfigFile() {
+ try {
+ URL newConfigurationURL = new URL(log4jConfigURLTextField.getText());
+ return new File(newConfigurationURL.toURI());
+ } catch (URISyntaxException e) {
+ e.printStackTrace();
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
}
}
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=1031469&r1=1031468&r2=1031469&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 Fri Nov 5 08:26:33 2010
@@ -10,6 +10,11 @@
<b>NOTE:</b> The mechanism and format used to persist settings in Chainsaw is subject to change. If you are experiencing problems displaying events in Chainsaw, please delete everything in the $user.dir/.chainsaw directory and restart Chainsaw.
<br>
<h1>2.1</h1>
+<h2>5 Nov 2010</h2>
+<ul>
+<li>Added ability to create log file receiver configurations from log4j xml configuration fileappender entries</li>
+<li>Added ability to save the receiver configuration from the receiver modification panel</li>
+</ul>
<h2>4 Nov 2010</h2>
<ul>
<li>Added ability to save the receiver configuration defined through the initial receiver configuration panel with a user-specified file path and name</li>