Skip to content

Commit 1ec3b58

Browse files
Change-Id: I47ab3999aae566ef3e0e512b8890bb8896fd8922
1 parent a98ef23 commit 1ec3b58

13 files changed

Lines changed: 234 additions & 17 deletions

README.md

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,49 @@ integrate Splunk best practice logging semantics into their code.
55
There are also custom handler/appender implementations for the 3 most prevalent Java logging frameworks in play.
66

77
1. LogBack
8-
2. log4j
8+
2. Log4j
99
3. java.util logging
1010

1111
This framework contains :
1212

1313
* Implementation of Splunk CIM(Common Information Model) and best practice logging semantics
14+
* java.util.logging handler for logging to Splunk REST endpoints
15+
* java.util.logging handler for logging to Splunk Raw TCP Server Socket
16+
* Log4j appender for logging to Splunk REST endpoints
17+
* Log4j appender for logging to Splunk Raw TCP Server Socket
18+
* Logback appender for logging to Splunk REST endpoints
19+
* Logback appender for logging to Splunk Raw TCP Server Socket
20+
* Example logging configuration files
21+
* Javadocs
1422

15-
* java.util.logging handler for logging to Splunk REST endpoints and Splunk Raw TCP Server Socket
23+
If you want to use UDP to send events to Splunk , then Log4j and Logback already have Syslog Appenders
24+
And of course you can still use any File appenders and have the file monitored by a Splunk Universal Forwarder.
1625

17-
* log4j appender for logging to Splunk REST endpoints and Splunk Raw TCP Server Socket
26+
## Resilience
1827

19-
* Logback appender for logging to Splunk REST endpoints and Splunk Raw TCP Server Socket
28+
The HTTP REST and Raw TCP handler/appenders have autonomous socket reconnection logic in case of connection failures.
29+
There is also internal event queuing that is loosely modelled off Splunk's outputs.conf for Universal Forwarders.
30+
You can set these propertys :
31+
* maxQueueSize : defaults to 500KB , format [<integer>|<integer>[KB|MB|GB]]
32+
* dropEventsOnQueueFull : defaults to false , format [ true | false]
2033

21-
* Example logging configuration files
34+
And you can use a parallel File appender if you absolutely need disk persistence.
2235

23-
* Javadocs
36+
## Data Cloning
2437

25-
If you want to use UDP to send events to Splunk , then Log4j and Logback already have Syslog Appenders
38+
If you want "data cloning" functionality, then you can leverage the logging configuration and have (n) different appender
39+
definitions for your various target Indexers.
40+
41+
## Load Balancing
42+
43+
A wrapper appender for Log4j and Logback is in the works.The design pattern is modelled off the Log4j "AsyncAppender" wrapper.
44+
So you will be able to define a "LoadBalancedAppender" and specify nested child appenders to Load Balance across.
45+
This opens up some interesting possibilitys such as load balancing across appenders that use the same or perhaps a
46+
mixture of different transports , REST / Raw TCP / Syslog.
47+
48+
## Thread Safety
49+
50+
Log4j and Logback are thread safe.
2651

2752
## License
2853

TODO

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
Build in final release Splunk Java SDK
2+
Load Balancing appender wrapper for log4j/logback

config/jdklogging.properties

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,15 @@ com.dtdsoftware.splunk.logging.jdk.handler.SplunkRestHandler.port=8089
2020
com.dtdsoftware.splunk.logging.jdk.handler.SplunkRestHandler.metaSource=rest
2121
com.dtdsoftware.splunk.logging.jdk.handler.SplunkRestHandler.metaSourcetype=testing
2222
com.dtdsoftware.splunk.logging.jdk.handler.SplunkRestHandler.metaIndex=main
23+
com.dtdsoftware.splunk.logging.jdk.handler.SplunkRestHandler.maxQueueSize=5MB
24+
com.dtdsoftware.splunk.logging.jdk.handler.SplunkRestHandler.dropEventsOnQueueFull=false
2325

2426
# Set the default logging level for new SplunkRawTCPHandler instances
2527
com.dtdsoftware.splunk.logging.jdk.handler.SplunkRawTCPHandler.level=INFO
2628
com.dtdsoftware.splunk.logging.jdk.handler.SplunkRawTCPHandler.host=localhost
2729
com.dtdsoftware.splunk.logging.jdk.handler.SplunkRawTCPHandler.port=5150
30+
com.dtdsoftware.splunk.logging.jdk.handler.SplunkRawTCPHandler.maxQueueSize=5MB
31+
com.dtdsoftware.splunk.logging.jdk.handler.SplunkRawTCPHandler.dropEventsOnQueueFull=false
2832

2933
# Set the default logging level for new ConsoleHandler instances
3034
java.util.logging.ConsoleHandler.level = INFO

config/log4j.properties

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ log4j.appender.splunkrest.delivery=stream
1818
log4j.appender.splunkrest.metaSource=rest
1919
log4j.appender.splunkrest.metaSourcetype=testing
2020
log4j.appender.splunkrest.metaIndex=main
21+
log4j.appender.splunkrest.maxQueueSize=5MB
22+
log4j.appender.splunkrest.dropEventsOnQueueFull=false
2123
log4j.appender.splunkrest.layout=org.apache.log4j.PatternLayout
2224
log4j.appender.splunkrest.layout.ConversionPattern=%m%n
2325
# optionally you can enrich the messages with formatting tokens from the logging framework
@@ -28,6 +30,8 @@ log4j.appender.splunkrest.layout.ConversionPattern=%m%n
2830
log4j.appender.splunkrawtcp=com.dtdsoftware.splunk.logging.log4j.appender.SplunkRawTCPAppender
2931
log4j.appender.splunkrawtcp.host=localhost
3032
log4j.appender.splunkrawtcp.port=5150
33+
log4j.appender.splunkrawtcp.maxQueueSize=5MB
34+
log4j.appender.splunkrawtcp.dropEventsOnQueueFull=false
3135
log4j.appender.splunkrawtcp.layout=org.apache.log4j.PatternLayout
3236
log4j.appender.splunkrawtcp.layout.ConversionPattern=%m%n
3337
# optionally you can enrich the messages with formatting tokens from the logging framework

config/logback.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
<user>admin</user>
1313
<metaSourcetype>testing</metaSourcetype>
1414
<pass>somepass</pass>
15+
<maxQueueSize>5MB</maxQueueSize>
16+
<dropEventsOnQueueFull>false</dropEventsOnQueueFull>
1517
<metaSource>rest</metaSource>
1618
<metaIndex>main</metaIndex>
1719
<layout class="ch.qos.logback.classic.PatternLayout">
@@ -27,6 +29,8 @@
2729
<appender name="splunkrawtcp" class="com.dtdsoftware.splunk.logging.logback.appender.SplunkRawTCPAppender">
2830
<port>5150</port>
2931
<host>localhost</host>
32+
<maxQueueSize>5MB</maxQueueSize>
33+
<dropEventsOnQueueFull>false</dropEventsOnQueueFull>
3034
<layout class="ch.qos.logback.classic.PatternLayout">
3135
<pattern>%m%n</pattern>
3236
<!-- optionally you can enrich the messages with formatting tokens from the logging framework

src/com/dtdsoftware/splunk/logging/SplunkRawTCPInput.java

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
*
1414
*/
1515

16-
public class SplunkRawTCPInput {
16+
public class SplunkRawTCPInput extends SplunkInput{
1717

1818
// connection props
1919
private String host = "";
@@ -78,17 +78,28 @@ public void closeStream() {
7878
* @param message
7979
*/
8080
public void streamEvent(String message) {
81-
81+
82+
String currentMessage = message;
8283
try {
8384

8485
if (writerOut != null) {
8586

86-
writerOut.write(message + "\n");
87-
writerOut.flush();
87+
//send the message
88+
writerOut.write(currentMessage + "\n");
8889

89-
}
90+
//flush the queue
91+
while(queueContainsEvents()){
92+
String messageOffQueue = dequeue();
93+
currentMessage = messageOffQueue;
94+
writerOut.write(currentMessage + "\n");
95+
}
96+
writerOut.flush();
97+
}
9098

9199
} catch (IOException e) {
100+
101+
//something went wrong , put message on the queue for retry
102+
enqueue(currentMessage);
92103
try {
93104
closeStream();
94105
} catch (Exception e1) {

src/com/dtdsoftware/splunk/logging/SplunkRestInput.java

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
*
1818
*/
1919

20-
public class SplunkRestInput {
20+
public class SplunkRestInput extends SplunkInput {
2121

2222
// Java SDK objects
2323
private Service service;
@@ -148,8 +148,23 @@ public void closeStream() {
148148
*/
149149
public void sendEvent(String message) {
150150

151-
if (streamSocket == null)
152-
this.receivers.submit(message, args);
151+
String currentMessage = message;
152+
153+
try {
154+
if (streamSocket == null) {
155+
this.receivers.submit(currentMessage, args);
156+
157+
// flush the queue
158+
while (queueContainsEvents()) {
159+
String messageOffQueue = dequeue();
160+
currentMessage = messageOffQueue;
161+
this.receivers.submit(currentMessage, args);
162+
}
163+
}
164+
} catch (Exception e) {
165+
// something went wrong , put message on the queue for retry
166+
enqueue(currentMessage);
167+
}
153168
}
154169

155170
/**
@@ -159,16 +174,28 @@ public void sendEvent(String message) {
159174
*/
160175
public void streamEvent(String message) {
161176

177+
String currentMessage = message;
162178
try {
163179

164180
if (writerOut != null) {
165181

166-
writerOut.write(message + "\n");
167-
writerOut.flush();
182+
// send the message
183+
writerOut.write(currentMessage + "\n");
168184

185+
// flush the queue
186+
while (queueContainsEvents()) {
187+
String messageOffQueue = dequeue();
188+
currentMessage = messageOffQueue;
189+
writerOut.write(currentMessage + "\n");
190+
}
191+
writerOut.flush();
169192
}
170193

171194
} catch (IOException e) {
195+
196+
// something went wrong , put message on the queue for retry
197+
enqueue(currentMessage);
198+
172199
try {
173200
closeStream();
174201
} catch (Exception e1) {

src/com/dtdsoftware/splunk/logging/jdk/handler/SplunkRawTCPHandler.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ public class SplunkRawTCPHandler extends Handler {
1818
// connection settings
1919
private String host = "";
2020
private int port = 5150;
21+
22+
//queuing settings
23+
private String maxQueueSize;
24+
private boolean dropEventsOnQueueFull;
2125

2226
private SplunkRawTCPInput sri;
2327

@@ -31,6 +35,8 @@ public SplunkRawTCPHandler() {
3135
try {
3236

3337
sri = new SplunkRawTCPInput(this.host, this.port);
38+
sri.setMaxQueueSize(maxQueueSize);
39+
sri.setDropEventsOnQueueFull(dropEventsOnQueueFull);
3440
} catch (Exception e) {
3541

3642
}
@@ -47,6 +53,8 @@ private void configure() {
4753

4854
setHost(manager.getProperty(cname + ".host"));
4955
setPort(Integer.parseInt(manager.getProperty(cname + ".port")));
56+
setMaxQueueSize(manager.getProperty(cname + ".maxQueueSize"));
57+
setDropEventsOnQueueFull(Boolean.parseBoolean(manager.getProperty(cname + ".dropEventsOnQueueFull")));
5058
setLevel(Level.parse(manager.getProperty(cname + ".level")));
5159
setFilter(null);
5260
setFormatter(new SplunkFormatter());
@@ -116,6 +124,23 @@ public void setPort(int port) {
116124
if (port > 0)
117125
this.port = port;
118126
}
127+
128+
public String getMaxQueueSize() {
129+
return maxQueueSize;
130+
}
131+
132+
public void setMaxQueueSize(String maxQueueSize) {
133+
this.maxQueueSize = maxQueueSize;
134+
}
135+
136+
public boolean isDropEventsOnQueueFull() {
137+
return dropEventsOnQueueFull;
138+
}
139+
140+
public void setDropEventsOnQueueFull(boolean dropEventsOnQueueFull) {
141+
this.dropEventsOnQueueFull = dropEventsOnQueueFull;
142+
}
143+
119144

120145
@Override
121146
public void flush() {

src/com/dtdsoftware/splunk/logging/jdk/handler/SplunkRestHandler.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ public class SplunkRestHandler extends Handler {
3333
private String metaHostRegex = "";
3434
private String metaHost = "";
3535

36+
//queuing settings
37+
private String maxQueueSize;
38+
private boolean dropEventsOnQueueFull;
39+
3640
private SplunkRestInput sri;
3741
private RestEventData red = new RestEventData();
3842

@@ -48,6 +52,8 @@ public SplunkRestHandler() {
4852
sri = new SplunkRestInput(this.user, this.pass, this.host,
4953
this.port, this.red, this.delivery.equals(STREAM) ? true
5054
: false);
55+
sri.setMaxQueueSize(maxQueueSize);
56+
sri.setDropEventsOnQueueFull(dropEventsOnQueueFull);
5157
} catch (Exception e) {
5258

5359
}
@@ -65,6 +71,7 @@ private void configure() {
6571
setUser(manager.getProperty(cname + ".user"));
6672
setPass(manager.getProperty(cname + ".pass"));
6773
setHost(manager.getProperty(cname + ".host"));
74+
6875
setDelivery(manager.getProperty(cname + ".delivery"));
6976
setPort(Integer.parseInt(manager.getProperty(cname + ".port")));
7077

@@ -74,6 +81,10 @@ private void configure() {
7481
setMetaIndex(manager.getProperty(cname + ".metaIndex"));
7582
setMetaSourcetype(manager.getProperty(cname + ".metaSourcetype"));
7683

84+
setMaxQueueSize(manager.getProperty(cname + ".maxQueueSize"));
85+
setDropEventsOnQueueFull(Boolean.parseBoolean(manager.getProperty(cname + ".dropEventsOnQueueFull")));
86+
87+
7788
setLevel(Level.parse(manager.getProperty(cname + ".level")));
7889
setFilter(null);
7990
setFormatter(new SplunkFormatter());
@@ -230,6 +241,22 @@ public void setMetaHost(String metaHost) {
230241
red.setHost(metaHost);
231242
}
232243
}
244+
245+
public String getMaxQueueSize() {
246+
return maxQueueSize;
247+
}
248+
249+
public void setMaxQueueSize(String maxQueueSize) {
250+
this.maxQueueSize = maxQueueSize;
251+
}
252+
253+
public boolean isDropEventsOnQueueFull() {
254+
return dropEventsOnQueueFull;
255+
}
256+
257+
public void setDropEventsOnQueueFull(boolean dropEventsOnQueueFull) {
258+
this.dropEventsOnQueueFull = dropEventsOnQueueFull;
259+
}
233260

234261
@Override
235262
public void flush() {

src/com/dtdsoftware/splunk/logging/log4j/appender/SplunkRawTCPAppender.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ public class SplunkRawTCPAppender extends AppenderSkeleton {
1818
private String host = "";
1919
private int port = 5150;
2020

21+
//queuing settings
22+
private String maxQueueSize;
23+
private boolean dropEventsOnQueueFull;
24+
2125
private SplunkRawTCPInput sri;
2226

2327
/**
@@ -46,6 +50,8 @@ protected void append(LoggingEvent event) {
4650
try {
4751
if (sri == null) {
4852
sri = new SplunkRawTCPInput(host, port);
53+
sri.setMaxQueueSize(maxQueueSize);
54+
sri.setDropEventsOnQueueFull(dropEventsOnQueueFull);
4955
}
5056
} catch (Exception e) {
5157
errorHandler
@@ -99,5 +105,21 @@ public int getPort() {
99105
public void setPort(int port) {
100106
this.port = port;
101107
}
108+
public String getMaxQueueSize() {
109+
return maxQueueSize;
110+
}
111+
112+
public void setMaxQueueSize(String maxQueueSize) {
113+
this.maxQueueSize = maxQueueSize;
114+
}
115+
116+
public boolean isDropEventsOnQueueFull() {
117+
return dropEventsOnQueueFull;
118+
}
119+
120+
public void setDropEventsOnQueueFull(boolean dropEventsOnQueueFull) {
121+
this.dropEventsOnQueueFull = dropEventsOnQueueFull;
122+
}
123+
102124

103125
}

0 commit comments

Comments
 (0)