(10, TimeUnit.SECONDS) {
@Override
protected String newObject() {
@@ -81,9 +82,8 @@ protected String newObject() {
* The TIMESTAMP field is the local time and is in the format of "Mmm dd hh:mm:ss" (without the quote marks)
*
*/
- rfc3164DateFormat = new ConcurrentDateFormat(
- "MMM dd HH:mm:ss",
- Locale.US,
+ rfc3164DateFormat = new ConcurrentRfc3164DateFormat(
+ Locale.getDefault(),
TimeZone.getDefault(),
concurrency);
}
diff --git a/src/main/java/com/cloudbees/syslog/util/ConcurrentRfc3164DateFormat.java b/src/main/java/com/cloudbees/syslog/util/ConcurrentRfc3164DateFormat.java
new file mode 100644
index 0000000..9095bf1
--- /dev/null
+++ b/src/main/java/com/cloudbees/syslog/util/ConcurrentRfc3164DateFormat.java
@@ -0,0 +1,101 @@
+package com.cloudbees.syslog.util;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+
+import javax.annotation.Nonnull;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingDeque;
+
+/**
+ * https://tools.ietf.org/html/rfc3164#section-4.1.2
+ *
+ * The TIMESTAMP field is the local time and is in the format of "Mmm dd
+ * hh:mm:ss" (without the quote marks) where:
+ *
+ * Mmm is the English language abbreviation for the month of the
+ * year with the first character in uppercase and the other two
+ * characters in lowercase. The following are the only acceptable
+ * values:
+ *
+ * Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec
+ *
+ * dd is the day of the month. If the day of the month is less
+ * than 10, then it MUST be represented as a space and then the
+ * number. For example, the 7th day of August would be
+ * represented as "Aug 7", with two spaces between the "g" and
+ * the "7".
+ *
+ * hh:mm:ss is the local time. The hour (hh) is represented in a
+ * 24-hour format. Valid entries are between 00 and 23,
+ * inclusive. The minute (mm) and second (ss) entries are between
+ * 00 and 59 inclusive.
+ *
+ */
+public class ConcurrentRfc3164DateFormat {
+ private final BlockingQueue monthDateFormats;
+ private final BlockingQueue timeDateFormats;
+ private final Locale locale;
+ private final TimeZone timeZone;
+
+ /**
+ * @param locale the locale whose date pattern symbols should be used
+ * @param timeZone the timezone used by the underlying calendar
+ * @param maxCacheSize
+ * @throws NullPointerException if the given pattern or locale is null
+ * @throws IllegalArgumentException if the given pattern is invalid
+ */
+ public ConcurrentRfc3164DateFormat(Locale locale, TimeZone timeZone, int maxCacheSize) {
+ this.monthDateFormats = new LinkedBlockingDeque<>(maxCacheSize);
+ this.timeDateFormats = new LinkedBlockingDeque<>(maxCacheSize);
+ this.locale = locale;
+ this.timeZone = timeZone;
+ }
+
+ /**
+ * Formats a Date into a date/time string.
+ *
+ * @param date the time value to be formatted into a time string.
+ * @return the formatted time string.
+ */
+ @Nonnull
+ @SuppressFBWarnings("RV_RETURN_VALUE_IGNORED_BAD_PRACTICE")
+ public String format(@Nonnull Date date) {
+
+
+ // MONTH
+
+ String month;
+
+
+ // DAY OF MONTH
+ GregorianCalendar calendar = new GregorianCalendar();
+ calendar.setTime(date);
+
+ int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
+ String dayofMonthPadding = dayOfMonth < 10 ? " " : "";
+
+ // TIME
+ SimpleDateFormat timeDateFormat = timeDateFormats.poll();
+ if (timeDateFormat == null) {
+ timeDateFormat = new SimpleDateFormat("HH:mm:ss", locale);
+ timeDateFormat.setTimeZone(timeZone);
+ }
+ String time;
+ try {
+ time = timeDateFormat.format(date);
+ } finally {
+ timeDateFormats.offer(timeDateFormat);
+ }
+
+ String result = month + ' ' + dayofMonthPadding + dayOfMonth + ' ' + time;
+
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "ConcurrentRfc3164DateFormat";
+ }
+}
diff --git a/src/test/java/com/cloudbees/syslog/SyslogMessageTest.java b/src/test/java/com/cloudbees/syslog/SyslogMessageTest.java
index 3f615cb..8f7c40a 100755
--- a/src/test/java/com/cloudbees/syslog/SyslogMessageTest.java
+++ b/src/test/java/com/cloudbees/syslog/SyslogMessageTest.java
@@ -95,7 +95,6 @@ public void testRfc5424FormatWithStructuredData() throws Exception {
System.out.println(SyslogMessage.rfc3339DateFormat.format(cal.getTime()));
System.out.println(cal.getTimeInMillis());
-
SyslogMessage message = new SyslogMessage()
.withTimestamp(cal.getTimeInMillis())
.withAppName("my_app")
@@ -119,15 +118,15 @@ public void testRfc5424FormatWithStructuredData() throws Exception {
}
@Test
- public void testRfc3164Format() throws Exception {
+ public void testRfc3164Format_withTwoDigitsDay() throws Exception {
Calendar cal = Calendar.getInstance();
cal.setTimeZone(TimeZone.getDefault());
- cal.set(2013, Calendar.DECEMBER, 5, 10, 30, 5);
+ cal.set(2013, Calendar.DECEMBER, 15, 10, 30, 5);
cal.set(Calendar.MILLISECOND, 0);
- System.out.println(SyslogMessage.rfc3339DateFormat.format(cal.getTime()));
- System.out.println(cal.getTimeInMillis());
+ // System.out.println(SyslogMessage.rfc3339DateFormat.format(cal.getTime()));
+ // System.out.println(cal.getTimeInMillis());
SyslogMessage message = new SyslogMessage()
@@ -140,9 +139,37 @@ public void testRfc3164Format() throws Exception {
.withMsg("a syslog message");
String actual = message.toRfc3164SyslogMessage();
- String expected = "<14>Dec 05 10:30:05 myserver.example.com my_app: a syslog message";
+ String expected = "<14>Dec 15 10:30:05 myserver.example.com my_app: a syslog message";
assertThat(actual, is(expected));
+ }
+
+ /**
+ * https://tools.ietf.org/html/rfc3164#section-4.1.2
+ */
+ @Test
+ public void testRfc3164Format_withSingleDigitDay() throws Exception {
+
+ Calendar cal = Calendar.getInstance();
+ cal.setTimeZone(TimeZone.getDefault());
+ cal.set(2013, Calendar.AUGUST, 7, 10, 30, 5);
+ cal.set(Calendar.MILLISECOND, 0);
+
+ // System.out.println(SyslogMessage.rfc3339DateFormat.format(cal.getTime()));
+ // System.out.println(cal.getTimeInMillis());
+ SyslogMessage message = new SyslogMessage()
+ .withTimestamp(cal.getTimeInMillis())
+ .withAppName("my_app")
+ .withHostname("myserver.example.com")
+ .withFacility(Facility.USER)
+ .withSeverity(Severity.INFORMATIONAL)
+ .withTimestamp(cal.getTimeInMillis())
+ .withMsg("a syslog message");
+
+ String actual = message.toRfc3164SyslogMessage();
+ String expected = "<14>Aug 7 10:30:05 myserver.example.com my_app: a syslog message";
+
+ assertThat(actual, is(expected));
}
}
diff --git a/src/test/java/com/cloudbees/syslog/sender/TcpSyslogMessageSenderTest.java b/src/test/java/com/cloudbees/syslog/sender/TcpSyslogMessageSenderTest.java
index 0889109..99edcb9 100644
--- a/src/test/java/com/cloudbees/syslog/sender/TcpSyslogMessageSenderTest.java
+++ b/src/test/java/com/cloudbees/syslog/sender/TcpSyslogMessageSenderTest.java
@@ -33,18 +33,23 @@ public class TcpSyslogMessageSenderTest {
@Test
public void send() throws Exception {
TcpSyslogMessageSender messageSender = new TcpSyslogMessageSender();
- messageSender.setDefaultMessageHostname("mysecretkey");
+ // messageSender.setDefaultMessageHostname("mysecretkey");
messageSender.setDefaultAppName("myapp");
messageSender.setDefaultFacility(Facility.USER);
messageSender.setDefaultSeverity(Severity.INFORMATIONAL);
- messageSender.setSyslogServerHostname("logs2.papertrailapp.com");
- messageSender.setSyslogServerPort(46022);
+
+ // messageSender.setSyslogServerHostname("logs2.papertrailapp.com");
+ // messageSender.setSyslogServerPort(46022);
+ // messageSender.setSsl(true);
+
+ messageSender.setSyslogServerHostname("localhost");
+ messageSender.setSyslogServerPort(9000);
+
messageSender.setMessageFormat(MessageFormat.RFC_3164);
- messageSender.setSsl(true);
messageSender.sendMessage("unit test message over tcp éèà " + getClass() + " - " + new Timestamp(System.currentTimeMillis()));
}
- @Ignore
+ // @Ignore
@Test
public void send2() throws Exception {
@@ -57,10 +62,15 @@ public void send2() throws Exception {
.withTimestamp(System.currentTimeMillis());
TcpSyslogMessageSender messageSender = new TcpSyslogMessageSender();
- messageSender.setSyslogServerHostname("logs2.papertrailapp.com");
- messageSender.setSyslogServerPort(46022);
+
+ // messageSender.setSyslogServerHostname("logs2.papertrailapp.com");
+ // messageSender.setSyslogServerPort(46022);
+ // messageSender.setSsl(true);
+
+ messageSender.setSyslogServerHostname("localhost");
+ messageSender.setSyslogServerPort(9000);
+
messageSender.setMessageFormat(MessageFormat.RFC_3164);
- messageSender.setSsl(true);
System.out.println(msg.toSyslogMessage(messageSender.getMessageFormat()));
diff --git a/src/test/java/com/cloudbees/syslog/util/ConcurrentRfc3164DateFormatTest.java b/src/test/java/com/cloudbees/syslog/util/ConcurrentRfc3164DateFormatTest.java
new file mode 100644
index 0000000..9f4fca6
--- /dev/null
+++ b/src/test/java/com/cloudbees/syslog/util/ConcurrentRfc3164DateFormatTest.java
@@ -0,0 +1,47 @@
+package com.cloudbees.syslog.util;
+
+import org.hamcrest.Matchers;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+public class ConcurrentRfc3164DateFormatTest {
+
+ @Test
+ public void test_format_date_with_single_digit_day_of_month(){
+ TimeZone timeZone = TimeZone.getTimeZone("UTC");
+ Calendar cal = Calendar.getInstance();
+ cal.setTimeZone(timeZone);
+ cal.set(2013, Calendar.AUGUST, 7, 10, 30, 5);
+ cal.set(Calendar.MILLISECOND, 0);
+
+ Date singleDigitDayOfMonthDate = cal.getTime();
+
+ ConcurrentRfc3164DateFormat rfc3164DateFormat = new ConcurrentRfc3164DateFormat(Locale.US, timeZone, 50);
+
+ String actual = rfc3164DateFormat.format(singleDigitDayOfMonthDate);
+
+ Assert.assertThat(actual, Matchers.is("Aug 7 10:30:05"));
+ }
+
+ @Test
+ public void test_format_date_with_double_digit_day_of_month(){
+ TimeZone timeZone = TimeZone.getTimeZone("UTC");
+ Calendar cal = Calendar.getInstance();
+ cal.setTimeZone(timeZone);
+ cal.set(2013, Calendar.AUGUST, 17, 10, 30, 5);
+ cal.set(Calendar.MILLISECOND, 0);
+
+ Date singleDigitDayOfMonthDate = cal.getTime();
+
+ ConcurrentRfc3164DateFormat rfc3164DateFormat = new ConcurrentRfc3164DateFormat(Locale.US, timeZone, 50);
+
+ String actual = rfc3164DateFormat.format(singleDigitDayOfMonthDate);
+
+ Assert.assertThat(actual, Matchers.is("Aug 17 10:30:05"));
+ }
+}