Skip to content
This repository was archived by the owner on Feb 5, 2026. It is now read-only.

Commit 91f15e9

Browse files
Log 11301 - InsightOps Java library should send data by TLS by default
* [LOG-11301] InsightOps Java library should send data by TLS by default
1 parent b08c34f commit 91f15e9

34 files changed

+1013
-1027
lines changed

README.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
[Please see our documentation page for usage information](https://insightops.help.rapid7.com/v1.0/docs/libraries)
1+
[Please see our documentation page for usage information](https://insightops.help.rapid7.com/docs/libraries)
22
-------
33

44
Logging To InsightOps from Java
55
==============================
66

7-
Logentries currently supports logging from Java using the following logging libraries:
7+
InsightOps currently supports logging from Java using the following logging libraries:
88

99
* [Log4J](https://insightops.help.rapid7.com/docs/log4j-log4j2)
1010
* [Log4J2](https://insightops.help.rapid7.com/docs/log4j-log4j2)
@@ -42,12 +42,10 @@ Logentries handler configuration (e.g. to support different tokens).
4242
```
4343
logger1.com.rapid7.jul.LogentriesHandler.token=4ff1cb0a-beea-4616-b647-1c113de8e7bb
4444
logger1.com.rapid7.jul.LogentriesHandler.region=eu
45-
logger1.com.rapid7.jul.LogentriesHandler.port=10000
4645
logger1.com.rapid7.jul.LogentriesHandler.formatter=java.util.logging.SimpleFormatter
4746
4847
logger2.com.rapid7.jul.LogentriesHandler.token=a70d9089-576c-4668-9641-14995d493a62
4948
logger2.com.rapid7.jul.LogentriesHandler.region=eu
50-
logger2.com.rapid7.jul.LogentriesHandler.port=10000
5149
logger2.com.rapid7.jul.LogentriesHandler.formatter=java.util.logging.SimpleFormatter
5250
```
5351

configFiles/log4j.properties.example

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ log4j.appender.le.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss ZZZ} %-5p: %F:
55
log4j.appender.le.Token=LOGENTRIES_TOKEN
66
log4j.appender.le.Region=eu
77
log4j.appender.le.Debug=False
8-
log4j.appender.le.Ssl=False
8+
log4j.appender.le.Ssl=true

configFiles/log4j.xml.example

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
33
<log4j:configuration debug="true">
44
<appender name="le" class="com.rapid7.log4j.LogentriesAppender">
5-
<!-- Enter your Logentries token, like bc0c4f90-a2d6-11e1-b3dd-0800200c9a66 -->
5+
<!-- Enter your log token, like 0c7407d4-fd0d-4436-bb50-44f1266b4490 -->
66
<param name="Token" value="LOGENTRIES_TOKEN" />
77
<param name="Region" value="eu" />
88
<param name="Debug" value="false" />
9-
<param name="Ssl" value="false" />
9+
<param name="Ssl" value="true" />
1010
<layout class="org.apache.log4j.PatternLayout">
1111
<param name="ConversionPattern"
1212
value="%d{yyyy-MM-dd HH:mm:ss ZZZ} %-5p (%F:%L) %m" />

configFiles/log4j2.xml.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
<debug>false</debug>
1010
<ignoreExceptions>false</ignoreExceptions>
1111
<logId></logId>
12+
<useSsl>true</useSsl>
1213
<!-- datahub specific options -->
1314
<key>account_key</key>
1415
<useDataHub>false</useDataHub>

configFiles/logback.xml.example

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<Token>LOGENTRIES_TOKEN</Token>
77
<Region>eu</Region>
88
<Debug>False</Debug>
9-
<Ssl>False</Ssl>
9+
<Ssl>true</Ssl>
1010
<facility>USER</facility>
1111
<encoder>
1212
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>

configFiles/logging.properties.example

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,4 @@ handlers = com.rapid7.jul.LogentriesHandler
33

44
com.rapid7.jul.LogentriesHandler.token = LOGENTRIES_TOKEN
55
com.rapid7.jul.LogentriesHandler.region = eu
6-
com.rapid7.jul.LogentriesHandler.port = 10000
76
com.rapid7.jul.LogentriesHandler.formatter = java.util.logging.SimpleFormatter

pom.xml

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
34

4-
<properties>
5-
<additionalparam>-Xdoclint:none</additionalparam>
5+
<properties>
6+
<additionalparam>-Xdoclint:none</additionalparam>
67
<guava.version>21.0</guava.version>
78
<jackson.version>2.4.2</jackson.version>
89
<log4j.version>2.7</log4j.version>
@@ -37,12 +38,10 @@
3738
</scm>
3839
<developers>
3940
<developer>
40-
<id>MarkLC</id>
41-
<name>Mark Lacomber</name>
42-
<email>marklacomber@gmail.com</email>
41+
<name>Rapid7</name>
42+
<email>InsightOpsTeam@rapid7.com</email>
4343
</developer>
4444
</developers>
45-
4645
<build>
4746
<plugins>
4847
<plugin>
@@ -80,6 +79,10 @@
8079
<artifactId>maven-surefire-plugin</artifactId>
8180
<version>2.19.1</version>
8281
<configuration>
82+
<systemPropertyVariables>
83+
<!--to Test tls/ssl mode connections in unit tests-->
84+
<javax.net.ssl.trustStore>target/test-classes/unit_test_key_store.jks</javax.net.ssl.trustStore>
85+
</systemPropertyVariables>
8386
<!-- Travis build workaround -->
8487
<forkCount>1</forkCount>
8588
<argLine>${surefire.jvm.params}</argLine>
@@ -152,7 +155,7 @@
152155
<groupId>com.lmax</groupId>
153156
<artifactId>disruptor</artifactId>
154157
<version>${disruptor.version}</version>
155-
<optional>true</optional>
158+
<optional>true</optional>
156159
</dependency>
157160
<dependency>
158161
<groupId>org.apache.logging.log4j</groupId>

src/main/java/com/rapid7/Constants.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,4 @@
33

44
public class Constants {
55
public static final String DATA_ENDPOINT_TEMPLATE = "%s.data.logs.insight.rapid7.com";
6-
public static final String HTTP_ENDPOINT_TEMPLATE = "%s.api.logs.insight.rapid7.com";
76
}

src/main/java/com/rapid7/jul/LogentriesHandler.java

Lines changed: 48 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
package com.rapid7.jul;
22

3-
import java.io.IOException;
4-
import java.net.InetSocketAddress;
5-
import java.nio.BufferOverflowException;
6-
import java.nio.ByteBuffer;
7-
import java.nio.channels.SocketChannel;
8-
import java.nio.charset.Charset;
3+
import com.rapid7.net.AsyncLogger;
4+
import com.rapid7.net.LoggerConfiguration;
5+
96
import java.text.MessageFormat;
107
import java.util.logging.Formatter;
118
import java.util.logging.Handler;
@@ -14,99 +11,51 @@
1411
import java.util.logging.LogRecord;
1512
import java.util.logging.SimpleFormatter;
1613

17-
import static com.google.common.base.Strings.isNullOrEmpty;
18-
import static com.rapid7.Constants.DATA_ENDPOINT_TEMPLATE;
19-
import static java.util.logging.ErrorManager.CLOSE_FAILURE;
2014
import static java.util.logging.ErrorManager.FORMAT_FAILURE;
2115
import static java.util.logging.ErrorManager.GENERIC_FAILURE;
22-
import static java.util.logging.ErrorManager.OPEN_FAILURE;
23-
import static java.util.logging.ErrorManager.WRITE_FAILURE;
2416

25-
/**
26-
* <code>LogentriesHandler</code>: A handler for writing formatted records to a
27-
* logentries.com. This handler uses the Token-based input.
28-
*
29-
* @author Björn Raupach (raupach@me.com)
30-
*/
31-
public final class LogentriesHandler extends Handler {
17+
public class LogentriesHandler extends Handler {
3218

33-
private final byte[] newline = {0x0D, 0x0A};
34-
private final byte space = 0x020;
35-
private String host;
36-
private int port;
37-
private byte[] token;
38-
private String region;
39-
private boolean open;
40-
private SocketChannel channel;
41-
private ByteBuffer buffer;
19+
/**
20+
* Asynchronous Background logger
21+
*/
22+
final AsyncLogger iopsAsync;
4223

4324
public LogentriesHandler() {
4425
this(null);
4526
}
4627

4728
public LogentriesHandler(String prefix) {
48-
configure(prefix);
49-
connect();
50-
buffer = ByteBuffer.allocate(4096);
51-
}
52-
53-
public String getHost() {
54-
return host;
55-
}
56-
57-
public void setHost(String host) {
58-
this.host = host;
59-
}
60-
61-
public int getPort() {
62-
return port;
29+
iopsAsync = new AsyncLogger(loadConfiguration(prefix));
6330
}
6431

65-
public void setPort(int port) {
66-
this.port = port;
67-
}
68-
69-
public byte[] getToken() {
70-
return token;
71-
}
72-
73-
public void setToken(byte[] token) {
74-
this.token = token;
75-
}
76-
77-
public String getRegion() {
78-
return region;
79-
}
80-
81-
public void setRegion(String region) {
82-
this.region = region;
32+
private LoggerConfiguration loadConfiguration(String prefix) {
33+
String cname = getClass().getName();
34+
String propsPrefix = prefix == null ? cname : prefix + "." + cname;
35+
setLevel(getLevelProperty(propsPrefix + ".level", Level.INFO));
36+
setFormatter(getFormatterProperty(propsPrefix + ".formatter", new SimpleFormatter()));
37+
return new LoggerConfiguration.Builder()
38+
.inRegion(getStringProperty(propsPrefix + ".region", ""))
39+
.toServerAddress(getStringProperty(propsPrefix + ".host", null))
40+
.toServerPort(getIntProperty(propsPrefix + ".port", 0))
41+
.useToken(getStringProperty(propsPrefix + ".token", ""))
42+
.useDataHub(getBooleanProperty(propsPrefix + ".useDataHub", false))
43+
.useHttpPut(getBooleanProperty(propsPrefix + ".httpPut", false))
44+
.useAccountKey(getStringProperty(propsPrefix + ".key", ""))
45+
.httpPutLocation(getStringProperty(propsPrefix + ".location", ""))
46+
.runInDebugMode(getBooleanProperty(propsPrefix + ".debug", false))
47+
.logHostNameAsPrefix(getBooleanProperty(propsPrefix + ".logHostName", false))
48+
.useAsHostName(getStringProperty(propsPrefix + ".hostNameToLog", ""))
49+
.setLogIdPrefix(getStringProperty(propsPrefix + ".logId", ""))
50+
.useSSL(getBooleanProperty(propsPrefix + ".ssl", true))
51+
.build();
8352
}
8453

8554

8655
@Override
8756
public synchronized void publish(LogRecord record) {
88-
if (open && isLoggable(record)) {
89-
String msg = formatMessage(record);
90-
if (!msg.isEmpty()) {
91-
boolean filled = fillAndFlip(msg);
92-
if (filled) {
93-
boolean drained = drain();
94-
if (!drained) {
95-
System.err.println("java.util.logging.ErrorManager: Sending to logentries.com failed. Trying to reconnect once.");
96-
connect();
97-
if (open) {
98-
filled = fillAndFlip(msg);
99-
if (filled) {
100-
drained = drain();
101-
if (!drained) {
102-
System.err.println("java.util.logging.ErrorManager: Unable to reconnect. Shutting handler down.");
103-
close();
104-
}
105-
}
106-
}
107-
}
108-
}
109-
}
57+
if (isLoggable(record)) {
58+
this.iopsAsync.addLineToQueue(formatMessage(record));
11059
}
11160
}
11261

@@ -122,77 +71,14 @@ String formatMessage(LogRecord record) {
12271
return msg;
12372
}
12473

125-
boolean fillAndFlip(String formattedMessage) {
126-
try {
127-
buffer.clear();
128-
buffer.put(token);
129-
buffer.put(space);
130-
buffer.put(formattedMessage.getBytes(Charset.forName("UTF-8")));
131-
buffer.put(newline);
132-
} catch (BufferOverflowException e) {
133-
reportError("Buffer exceeds capacity", e, WRITE_FAILURE);
134-
return false;
135-
}
136-
buffer.flip();
137-
return true;
138-
}
139-
140-
boolean drain() {
141-
while (buffer.hasRemaining()) {
142-
try {
143-
channel.write(buffer);
144-
} catch (Exception e) {
145-
reportError("Error while writing channel.", e, WRITE_FAILURE);
146-
return false;
147-
}
148-
}
149-
return true;
150-
}
151-
152-
void configure(String prefix) {
153-
String cname = getClass().getName();
154-
String propsPrefix = prefix == null ? cname : prefix + "." + cname;
155-
setLevel(getLevelProperty(propsPrefix + ".level", Level.INFO));
156-
setFormatter(getFormatterProperty(propsPrefix + ".formatter", new SimpleFormatter()));
157-
setRegion(getStringProperty(propsPrefix + ".region", ""));
158-
159-
String hostProperty = getStringProperty(propsPrefix + ".host", null);
160-
if (isNullOrEmpty(hostProperty)) {
161-
setHost(String.format(DATA_ENDPOINT_TEMPLATE, region));
162-
} else {
163-
setHost(hostProperty);
164-
}
165-
166-
setPort(getIntProperty(propsPrefix + ".port", 514));
167-
setToken(getBytesProperty(propsPrefix + ".token", ""));
168-
}
169-
170-
void connect() {
171-
try {
172-
channel = SocketChannel.open();
173-
channel.connect(new InetSocketAddress(host, port));
174-
open = true;
175-
} catch (IOException e) {
176-
open = false;
177-
reportError(MessageFormat.format("Error connection to host: {0}:{1}", host, port), e, OPEN_FAILURE);
178-
}
179-
}
180-
18174
@Override
18275
public void flush() {
76+
// no need to flush since the log is sent by AsyncLogger
18377
}
18478

18579
@Override
186-
public void close() throws SecurityException {
187-
open = false;
188-
buffer = null;
189-
if (channel != null) {
190-
try {
191-
channel.close();
192-
} catch (IOException e) {
193-
reportError("Error while closing channel.", e, CLOSE_FAILURE);
194-
}
195-
}
80+
public void close() {
81+
iopsAsync.close();
19682
}
19783

19884
// -- These methods are private in LogManager
@@ -235,8 +121,20 @@ String getStringProperty(String name, String defaultValue) {
235121
return val.trim();
236122
}
237123

238-
byte[] getBytesProperty(String name, String defaultValue) {
239-
return getStringProperty(name, defaultValue).getBytes();
124+
boolean getBooleanProperty(String name, boolean defaultValue) {
125+
LogManager manager = LogManager.getLogManager();
126+
String val = manager.getProperty(name);
127+
if (val == null) {
128+
return defaultValue;
129+
}
130+
if ("false".equalsIgnoreCase(val.trim())) {
131+
return false;
132+
} else if ("true".equalsIgnoreCase(val.trim())) {
133+
return true;
134+
} else {
135+
reportError(MessageFormat.format("Error reading property ''{0}''", name), null, GENERIC_FAILURE);
136+
return defaultValue;
137+
}
240138
}
241139

242140
int getIntProperty(String name, int defaultValue) {

0 commit comments

Comments
 (0)