Hi everyone!
I've came here with a little patch to allow SyslogAppender use TCP instead of
UDP as transport.
TCP syslog is not standartized, but supported by numerous syslog servers
nevertheless. Here at CTXM we are required to log to a syslog server via TCP
because of some firewall issues.
Usage is something like this:
----------------------------------------
# file log4j.properties
log4j.rootCategory=ALL, SyslogApender
log4j.appender.SyslogApender=org.apache.log4j.net.SyslogAppender
log4j.appender.SyslogApender.layout=org.apache.log4j.PatternLayout
log4j.appender.SyslogApender.layout.ConversionPattern=[%-5p] %c{1} - %m%n
# note the "tcp:" prefix
log4j.appender.SyslogApender.syslogHost=tcp:localhost:514
----------------------------------------
The patch is against Log4J 1.2.15. The @since tag in the TCPSyslogWriter and
the "version" property in build.xml probably needs to be corrected :)
--
Daniil V. Kolpakov
Software developer
CTXM SIA
www.ctxm.com
--
This message has been scanned for viruses and
dangerous content and is believed to be clean.
diff --new-file --exclude=dist --exclude='*.jar' --exclude='*~' --recursive --unified apache-log4j-1.2.15/build.xml apache-log4j-1.2.15-tcp-patch/build.xml
--- apache-log4j-1.2.15/build.xml 2007-08-25 07:09:43.000000000 +0300
+++ apache-log4j-1.2.15-tcp-patch/build.xml 2007-11-28 12:40:32.000000000 +0200
@@ -39,7 +39,7 @@
<!-- prefixed with "env". -->
<property environment="env"/>
- <property name="version" value="1.2.15"/>
+ <property name="version" value="1.2.15-tcp-patch"/>
<!-- The base directory relative to which most targets are built -->
<property name="base" value="."/>
diff --new-file --exclude=dist --exclude='*.jar' --exclude='*~' --recursive --unified apache-log4j-1.2.15/src/main/java/org/apache/log4j/helpers/TCPSyslogWriter.java apache-log4j-1.2.15-tcp-patch/src/main/java/org/apache/log4j/helpers/TCPSyslogWriter.java
--- apache-log4j-1.2.15/src/main/java/org/apache/log4j/helpers/TCPSyslogWriter.java 1970-01-01 03:00:00.000000000 +0300
+++ apache-log4j-1.2.15-tcp-patch/src/main/java/org/apache/log4j/helpers/TCPSyslogWriter.java 2007-11-28 13:24:12.000000000 +0200
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.net.Socket;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * TCPSyslogWriter mimics [EMAIL PROTECTED] SyslogWriter} behavior,
+ * but sends each peace of data (normally, a String) over a TCP socket.
+ * The socket is opened and closed on each write.
+ *
+ * @since 1.2.15-tcp-patch
+ * @author Daniil V. Kolpakov (ctxm.com)
+ */
+public class TCPSyslogWriter extends Writer {
+ static final int SYSLOG_TCP_PORT = 514;
+
+ private transient final String host;
+ private transient final int port;
+
+ /**
+ * Regular expression pattern to match "tcp:host:port" string, with
+ * capturing groups for host and port parts. The host can be surrounded by
+ * a pair of square brackets, and the tcp: part is optional
+ */
+ final static Pattern hostPortPattern =
+ Pattern.compile("(?:tcp:)? # optional tcp: prefix\n"
+ + "(?: # \n"
+ + "\\[ # opening bracket\n"
+ + "([^\\]]+) # IPv6 host: any chars except. ']'\n"
+ + "] # closing bracket\n"
+ + "| # \n"
+ + "([^:]+)) # IPv4 host or domain name\n"
+ + "(?: # optional part start\n"
+ + ": # colon\n"
+ + "(\\d+) # port (digits)\n"
+ + ")? # optional part end",
+ Pattern.COMMENTS);
+
+ /**
+ * Creates new writer based on the tcp:host:port specification. The ":port"
+ * part is optional; the "tcp:" prefix is optional too; the port is decimal.
+ * If you need to specify IPv6 address, enclose it in square brackets.
+ *
+ * @param hostPort the host:port specification
+ */
+ public TCPSyslogWriter(String hostPort) {
+ final Matcher m = hostPortPattern.matcher(hostPort);
+ if (m.matches()) {
+ if (m.group(1) == null) {
+ this.host = m.group(2); // IPv4 or domain name
+ } else {
+ this.host = m.group(1); //IPv6
+ }
+ if (m.group(3) == null) {
+ this.port = SYSLOG_TCP_PORT;
+ } else {
+ this.port = Integer.parseInt(m.group(3));
+ }
+ } else {
+ LogLog.error("Could not parse host:port parameter (" + hostPort
+ + "). All logging will FAIL.");
+ this.host = null;
+ this.port = -1;
+ }
+ }
+
+ /**
+ * No-op, since instances of this class do not hold any open resources
+ * between write()'s
+ */
+ public void close() {
+ }
+
+ /**
+ * No-op, since output is not buffered
+ */
+ public void flush() {
+ }
+
+ /**
+ * Opens TCP socket connection, sends the [EMAIL PROTECTED] data} specified and
+ * closes the connection.
+ */
+ public void write(final String data) throws IOException {
+ if (host != null) {
+ final Socket socket = new Socket(host, port);
+ final OutputStream out = socket.getOutputStream();
+ out.write(data.getBytes());
+ out.close();
+ socket.close();
+ }
+ }
+
+ /**
+ * Opens TCP socket connection, sends the [EMAIL PROTECTED] count} chars out of the
+ * [EMAIL PROTECTED] data} parameter starting with [EMAIL PROTECTED] start} and closes the
+ * connection.
+ */
+ public void write(final char[] data,
+ final int start,
+ final int count) throws IOException {
+ write(new String(data, start, count));
+ }
+}
diff --new-file --exclude=dist --exclude='*.jar' --exclude='*~' --recursive --unified apache-log4j-1.2.15/src/main/java/org/apache/log4j/net/SyslogAppender.java apache-log4j-1.2.15-tcp-patch/src/main/java/org/apache/log4j/net/SyslogAppender.java
--- apache-log4j-1.2.15/src/main/java/org/apache/log4j/net/SyslogAppender.java 2007-08-25 07:09:40.000000000 +0300
+++ apache-log4j-1.2.15-tcp-patch/src/main/java/org/apache/log4j/net/SyslogAppender.java 2007-11-28 13:05:58.000000000 +0200
@@ -21,6 +21,7 @@
import org.apache.log4j.Layout;
import org.apache.log4j.helpers.SyslogQuietWriter;
import org.apache.log4j.helpers.SyslogWriter;
+import org.apache.log4j.helpers.TCPSyslogWriter;
import org.apache.log4j.spi.LoggingEvent;
import java.text.SimpleDateFormat;
@@ -28,12 +29,15 @@
import java.util.Locale;
import java.net.InetAddress;
import java.net.UnknownHostException;
+import java.io.Writer;
// Contributors: Yves Bossel <[EMAIL PROTECTED]>
// Christopher Taylor <[EMAIL PROTECTED]>
+// Daniil Kolpakov <[EMAIL PROTECTED]>
/**
- Use SyslogAppender to send log messages to a remote syslog daemon.
+ Use SyslogAppender to send log messages to a remote syslog (RFC 3164)
+ daemon, either via UDP or TCP transport
@author Ceki Gülcü
@author Anders Kristensen
@@ -373,14 +377,24 @@
where log output should go. A non-default port can be specified by
appending a colon and port number to a host name,
an IPv4 address or an IPv6 address enclosed in square brackets.
+ Use "tcp:" prefix to specify that this appender must use TCP transport
+ instead of UDP (note: this is not the same as RFC 3165, but a non-standart
+ mode of operation when regular syslog messages are sent over TCP instead
+ of UDP).
<b>WARNING</b> If the SyslogHost is not set, then this appender
will fail.
*/
public
void setSyslogHost(final String syslogHost) {
- this.sqw = new SyslogQuietWriter(new SyslogWriter(syslogHost),
- syslogFacility, errorHandler);
+ final Writer syslogWriter;
+ if (syslogHost.startsWith("tcp:")) {
+ syslogWriter = new TCPSyslogWriter(syslogHost);
+ } else {
+ syslogWriter = new SyslogWriter(syslogHost);
+ }
+ this.sqw = new SyslogQuietWriter(syslogWriter,
+ syslogFacility, errorHandler);
//this.stp = new SyslogTracerPrintWriter(sqw);
this.syslogHost = syslogHost;
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]