INT-3450 Support RFC 5424/6587 for SYSLOG

JIRA: https://jira.spring.io/browse/INT-3450

Use LinkedHashMap

- natural iteration order

INT-3450 Polishing - PR Comments

INT-3450: Polishing
This commit is contained in:
Gary Russell
2014-12-11 22:27:41 +02:00
committed by Artem Bilan
parent 1a4f98ac4c
commit 864cabcfe0
10 changed files with 927 additions and 7 deletions

View File

@@ -54,9 +54,18 @@
connection-factory="cf"
auto-startup="false"
phase="123"
converter="converter"
converter="rfc5424"
send-timeout="456"
error-channel="errors" />
<int-ip:tcp-connection-factory id="cf" type="server" port="1514" />
<int-ip:tcp-connection-factory id="cf"
using-nio="true"
type="server"
port="1514"
deserializer="rfc6587" />
<bean id="rfc5424" class="org.springframework.integration.syslog.RFC5424MessageConverter" />
<bean id="rfc6587" class="org.springframework.integration.syslog.inbound.RFC6587SyslogDeserializer" />
</beans>

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,9 +37,9 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.ip.tcp.connection.AbstractConnectionFactory;
import org.springframework.integration.ip.tcp.connection.AbstractServerConnectionFactory;
import org.springframework.integration.syslog.MessageConverter;
import org.springframework.integration.syslog.RFC5424MessageConverter;
import org.springframework.integration.syslog.inbound.TcpSyslogReceivingChannelAdapter;
import org.springframework.integration.syslog.inbound.UdpSyslogReceivingChannelAdapter;
import org.springframework.integration.test.util.TestUtils;
@@ -81,6 +81,9 @@ public class SyslogReceivingChannelAdapterParserTests {
@Autowired
private PassThruConverter converter;
@Autowired
private RFC5424MessageConverter rfc5424;
@Autowired @Qualifier("bar.adapter")
private TcpSyslogReceivingChannelAdapter adapter2;
@@ -152,7 +155,7 @@ public class SyslogReceivingChannelAdapterParserTests {
assertFalse(fullBoatTcp.isAutoStartup());
assertEquals(123, fullBoatTcp.getPhase());
assertEquals(456L, TestUtils.getPropertyValue(fullBoatUdp, "messagingTemplate.sendTimeout"));
assertSame(converter, TestUtils.getPropertyValue(fullBoatTcp, "converter"));
assertSame(rfc5424, TestUtils.getPropertyValue(fullBoatTcp, "converter"));
assertSame(errors, TestUtils.getPropertyValue(fullBoatTcp, "errorChannel"));
assertSame(cf, TestUtils.getPropertyValue(fullBoatTcp, "connectionFactory"));
}

View File

@@ -0,0 +1,141 @@
/*
* Copyright 2014 the original author or authors.
*
* 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.springframework.integration.syslog.inbound;
import static org.junit.Assert.assertEquals;
import java.io.ByteArrayInputStream;
import java.util.List;
import java.util.Map;
import org.junit.Test;
import org.springframework.integration.syslog.SyslogHeaders;
/**
* @author Duncan McIntyre
* @author Gary Russell
* @since 4.1.1
*
*/
public class SyslogDeserializerTests {
static final String VALID_UNFRAMED_ENTRY =
"<14>1 2014-06-20T09:14:07+00:00 loggregator d0602076-b14a-4c55-852a-981e7afeed38 DEA - - Removing instance\n";
static final String VALID_FRAMED_ENTRY =
"106 <14>1 2014-06-20T09:14:07+00:00 loggregator d0602076-b14a-4c55-852a-981e7afeed38 DEA - - Removing instance";
static final String SHORT_FRAMED_ENTRY =
"107 <14>1 2014-06-20T09:14:07+00:00 loggregator d0602076-b14a-4c55-852a-981e7afeed38 DEA - - Removing instance";
static final String SD_ENTRY_1 =
"179 <14>1 2014-06-20T09:14:07+00:00 loggregator d0602076-b14a-4c55-852a-981e7afeed38 DEA - " +
"[exampleSDID@32473 iut=\\\"3\\\" eventSource=\\\"Application\\\" eventID=\\\"1011\\\"] Removing instance";
static final String SD_ENTRY_2 =
"253 <14>1 2014-06-20T09:14:07+00:00 loggregator d0602076-b14a-4c55-852a-981e7afeed38 DEA - " +
"[exampleSDID@32473 iut=\\\"3\\\" eventSource=\\\"Application\\\" eventID=\\\"1011\\\"][exampleSDID@32473 " +
"iut=\\\"3\\\" eventSource=\\\"Application\\\" eventID=\\\"1011\\\"] Removing instance";
static final String SD_ENTRY_3 = "275 <14>1 2014-06-20T09:14:07+00:00 loggregator d0602076-b14a-4c55-852a-981e7afeed38 DEA - " +
"[exampleSDID@32473 iut=\\\"3\\\" eventSource=\\\"Application\\\" eventID=\\\"1011\\\"][exampleSDID@32473 " +
"iut=\\\"3\\\" eventSource=\\\"Application\\\" escapedBracket=\\\"\\]\\\" eventID=\\\"1011\\\"] Removing instance";
@Test
public void shouldParseAValidFramedEntry() throws Exception {
RFC6587SyslogDeserializer deserializer = new RFC6587SyslogDeserializer();
Map<String, ?> map = deserializer.deserialize(new ByteArrayInputStream(VALID_FRAMED_ENTRY.getBytes()));
assertEquals(1, map.get(SyslogHeaders.FACILITY));
assertEquals(6, map.get(SyslogHeaders.SEVERITY));
assertEquals(1, map.get(SyslogHeaders.VERSION));
assertEquals("2014-06-20T09:14:07+00:00", map.get(SyslogHeaders.TIMESTAMP));
assertEquals("loggregator", map.get(SyslogHeaders.HOST));
assertEquals("d0602076-b14a-4c55-852a-981e7afeed38", map.get(SyslogHeaders.APP_NAME));
assertEquals("DEA", map.get(SyslogHeaders.PROCID));
assertEquals("-", map.get(SyslogHeaders.MSGID));
assertEquals("Removing instance", map.get(SyslogHeaders.MESSAGE));
}
@Test
public void shouldParseAValidUnframedEntry() throws Exception {
RFC6587SyslogDeserializer deserializer = new RFC6587SyslogDeserializer();
Map<String, ?> map = deserializer.deserialize(new ByteArrayInputStream(VALID_UNFRAMED_ENTRY.getBytes()));
assertEquals(1, map.get(SyslogHeaders.FACILITY));
assertEquals(6, map.get(SyslogHeaders.SEVERITY));
assertEquals(1, map.get(SyslogHeaders.VERSION));
assertEquals("2014-06-20T09:14:07+00:00", map.get(SyslogHeaders.TIMESTAMP));
assertEquals("loggregator", map.get(SyslogHeaders.HOST));
assertEquals("d0602076-b14a-4c55-852a-981e7afeed38", map.get(SyslogHeaders.APP_NAME));
assertEquals("DEA", map.get(SyslogHeaders.PROCID));
assertEquals("-", map.get(SyslogHeaders.MSGID));
assertEquals("Removing instance", map.get(SyslogHeaders.MESSAGE));
}
@Test
public void shouldGetStructuredData() throws Exception {
RFC6587SyslogDeserializer deserializer = new RFC6587SyslogDeserializer();
Map<String, ?> map = deserializer.deserialize(new ByteArrayInputStream(SD_ENTRY_1.getBytes()));
assertEquals(1, map.get(SyslogHeaders.FACILITY));
assertEquals(6, map.get(SyslogHeaders.SEVERITY));
assertEquals(1, map.get(SyslogHeaders.VERSION));
assertEquals("2014-06-20T09:14:07+00:00", map.get(SyslogHeaders.TIMESTAMP));
assertEquals("loggregator", map.get(SyslogHeaders.HOST));
assertEquals("d0602076-b14a-4c55-852a-981e7afeed38", map.get(SyslogHeaders.APP_NAME));
assertEquals("DEA", map.get(SyslogHeaders.PROCID));
assertEquals("-", map.get(SyslogHeaders.MSGID));
assertEquals("Removing instance", map.get(SyslogHeaders.MESSAGE));
assertEquals(1, ((List<?>) map.get(SyslogHeaders.STRUCTURED_DATA)).size());
}
@Test
public void shouldGetMultipleStructuredData() throws Exception {
RFC6587SyslogDeserializer deserializer = new RFC6587SyslogDeserializer();
Map<String, ?> map = deserializer.deserialize(new ByteArrayInputStream(SD_ENTRY_2.getBytes()));
assertEquals("false", map.get(SyslogHeaders.DECODE_ERRORS));
assertEquals("Removing instance", map.get(SyslogHeaders.MESSAGE));
assertEquals(2, ((List<?>) map.get(SyslogHeaders.STRUCTURED_DATA)).size());
}
@Test
public void shouldGetMultipleStructuredDataWithEscapedBracket() throws Exception {
RFC6587SyslogDeserializer deserializer = new RFC6587SyslogDeserializer();
Map<String, ?> map = deserializer.deserialize(new ByteArrayInputStream(SD_ENTRY_3.getBytes()));
assertEquals("false", map.get(SyslogHeaders.DECODE_ERRORS));
assertEquals("Removing instance", map.get(SyslogHeaders.MESSAGE));
}
@Test
public void shouldErrorOnShortFramedData() throws Exception {
RFC6587SyslogDeserializer deserializer = new RFC6587SyslogDeserializer();
Map<String, ?> map = deserializer.deserialize(new ByteArrayInputStream(SHORT_FRAMED_ENTRY.getBytes()));
assertEquals("true", map.get(SyslogHeaders.DECODE_ERRORS));
}
}

View File

@@ -29,6 +29,7 @@ import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -44,7 +45,10 @@ import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.ip.tcp.connection.AbstractServerConnectionFactory;
import org.springframework.integration.ip.tcp.connection.TcpNioServerConnectionFactory;
import org.springframework.integration.syslog.DefaultMessageConverter;
import org.springframework.integration.syslog.RFC5424MessageConverter;
import org.springframework.integration.syslog.config.SyslogReceivingChannelAdapterFactoryBean;
import org.springframework.integration.test.util.SocketUtils;
import org.springframework.integration.test.util.TestUtils;
@@ -109,7 +113,7 @@ public class SyslogReceivingChannelAdapterTests {
Log logger = spy(TestUtils.getPropertyValue(adapter, "logger", Log.class));
doReturn(true).when(logger).isDebugEnabled();
final CountDownLatch sawLog = new CountDownLatch(1);
doAnswer(new Answer<Void>(){
doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
@@ -163,4 +167,91 @@ public class SyslogReceivingChannelAdapterTests {
adapter.stop();
}
@Test
public void testTcpRFC5424() throws Exception {
SyslogReceivingChannelAdapterFactoryBean factory = new SyslogReceivingChannelAdapterFactoryBean(
SyslogReceivingChannelAdapterFactoryBean.Protocol.tcp);
int port = SocketUtils.findAvailableServerSocket(1514);
PollableChannel outputChannel = new QueueChannel();
factory.setOutputChannel(outputChannel);
ApplicationEventPublisher publisher = mock(ApplicationEventPublisher.class);
final CountDownLatch latch = new CountDownLatch(2);
doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
latch.countDown();
return null;
}
}).when(publisher).publishEvent(any(ApplicationEvent.class));
factory.setBeanFactory(mock(BeanFactory.class));
AbstractServerConnectionFactory connectionFactory = new TcpNioServerConnectionFactory(port);
connectionFactory.setDeserializer(new RFC6587SyslogDeserializer());
connectionFactory.setApplicationEventPublisher(publisher);
factory.setConnectionFactory(connectionFactory);
factory.setConverter(new RFC5424MessageConverter());
factory.afterPropertiesSet();
factory.start();
TcpSyslogReceivingChannelAdapter adapter = (TcpSyslogReceivingChannelAdapter) factory.getObject();
Log logger = spy(TestUtils.getPropertyValue(adapter, "logger", Log.class));
doReturn(true).when(logger).isDebugEnabled();
final CountDownLatch sawLog = new CountDownLatch(1);
doAnswer(new Answer<Void>(){
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
if (((String) invocation.getArguments()[0]).contains("Error on syslog socket")) {
sawLog.countDown();
}
invocation.callRealMethod();
return null;
}
}).when(logger).debug(anyString());
new DirectFieldAccessor(adapter).setPropertyValue("logger", logger);
Thread.sleep(1000);
byte[] buf = ("253 <14>1 2014-06-20T09:14:07+00:00 loggregator d0602076-b14a-4c55-852a-981e7afeed38 DEA - " +
"[exampleSDID@32473 iut=\\\"3\\\" eventSource=\\\"Application\\\" eventID=\\\"1011\\\"]" +
"[exampleSDID@32473 iut=\\\"3\\\" eventSource=\\\"Application\\\" eventID=\\\"1011\\\"] Removing instance")
.getBytes("UTF-8");
Socket socket = SocketFactory.getDefault().createSocket("localhost", port);
socket.getOutputStream().write(buf);
socket.close();
assertTrue(sawLog.await(10, TimeUnit.SECONDS));
@SuppressWarnings("unchecked")
Message<Map<String, ?>> message = (Message<Map<String, ?>>) outputChannel.receive(10000);
assertNotNull(message);
assertEquals("loggregator", message.getPayload().get("syslog_HOST"));
adapter.stop();
assertTrue(latch.await(10, TimeUnit.SECONDS));
}
@Test
public void testUdpRFC5424() throws Exception {
SyslogReceivingChannelAdapterFactoryBean factory = new SyslogReceivingChannelAdapterFactoryBean(
SyslogReceivingChannelAdapterFactoryBean.Protocol.udp);
int port = SocketUtils.findAvailableUdpSocket(1514);
factory.setPort(port);
PollableChannel outputChannel = new QueueChannel();
factory.setOutputChannel(outputChannel);
factory.setBeanFactory(mock(BeanFactory.class));
factory.setConverter(new RFC5424MessageConverter());
factory.afterPropertiesSet();
factory.start();
UdpSyslogReceivingChannelAdapter adapter = (UdpSyslogReceivingChannelAdapter) factory.getObject();
Thread.sleep(1000);
byte[] buf = ("<14>1 2014-06-20T09:14:07+00:00 loggregator d0602076-b14a-4c55-852a-981e7afeed38 DEA - " +
"[exampleSDID@32473 iut=\\\"3\\\" eventSource=\\\"Application\\\" eventID=\\\"1011\\\"]" +
"[exampleSDID@32473 iut=\\\"3\\\" eventSource=\\\"Application\\\" eventID=\\\"1011\\\"] Removing instance")
.getBytes("UTF-8");
DatagramPacket packet = new DatagramPacket(buf, buf.length, new InetSocketAddress("localhost", port));
DatagramSocket socket = new DatagramSocket();
socket.send(packet);
socket.close();
@SuppressWarnings("unchecked")
Message<Map<String, ?>> message = (Message<Map<String, ?>>) outputChannel.receive(10000);
assertNotNull(message);
assertEquals("loggregator", message.getPayload().get("syslog_HOST"));
adapter.stop();
}
}