New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
Gelf writer #590
Gelf writer #590
Changes from 10 commits
9f56419
c5f5a93
2e63474
abcf5f8
6b6c266
52a090f
378a7bf
ab9fba4
c7ab0e0
19ac1b7
25a08a1
d769aa0
0d2dcf3
d898888
6d6b2df
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!-- | ||
|
||
The MIT License | ||
Copyright 漏 2010 JmxTrans team | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in | ||
all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
THE SOFTWARE. | ||
|
||
--> | ||
<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/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
<parent> | ||
<groupId>org.jmxtrans</groupId> | ||
<artifactId>jmxtrans-output</artifactId> | ||
<version>266-SNAPSHOT</version> | ||
</parent> | ||
|
||
<artifactId>jmxtrans-output-gelf</artifactId> | ||
|
||
<name>JmxTrans - GELF output writers</name> | ||
|
||
<properties> | ||
<verify.mutationThreshold>53</verify.mutationThreshold> | ||
<verify.totalBranchRate>35</verify.totalBranchRate> | ||
<verify.totalLineRate>97</verify.totalLineRate> | ||
</properties> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>commons-lang</groupId> | ||
<artifactId>commons-lang</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.graylog2</groupId> | ||
<artifactId>gelfclient</artifactId> | ||
<version>1.4.0</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.jmxtrans</groupId> | ||
<artifactId>jmxtrans-core</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.jmxtrans</groupId> | ||
<artifactId>jmxtrans-output-core</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.projectlombok</groupId> | ||
<artifactId>lombok</artifactId> | ||
<scope>provided</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>junit</groupId> | ||
<artifactId>junit</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.assertj</groupId> | ||
<artifactId>assertj-core</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.jmxtrans</groupId> | ||
<artifactId>jmxtrans-test-utils</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.mockito</groupId> | ||
<artifactId>mockito-core</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> | ||
</project> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
/** | ||
* The MIT License | ||
* Copyright 漏 2010 JmxTrans team | ||
* | ||
* Permission is hereby granted, free of charge, to any person obtaining a copy | ||
* of this software and associated documentation files (the "Software"), to deal | ||
* in the Software without restriction, including without limitation the rights | ||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
* copies of the Software, and to permit persons to whom the Software is | ||
* furnished to do so, subject to the following conditions: | ||
* | ||
* The above copyright notice and this permission notice shall be included in | ||
* all copies or substantial portions of the Software. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
* THE SOFTWARE. | ||
*/ | ||
package com.googlecode.jmxtrans.model.output.gelf; | ||
|
||
import com.google.common.collect.ImmutableList; | ||
import com.googlecode.jmxtrans.model.OutputWriterAdapter; | ||
import com.googlecode.jmxtrans.model.Query; | ||
import com.googlecode.jmxtrans.model.Result; | ||
import com.googlecode.jmxtrans.model.Server; | ||
import com.googlecode.jmxtrans.model.naming.KeyUtils; | ||
import lombok.EqualsAndHashCode; | ||
import org.apache.commons.lang.StringUtils; | ||
import org.graylog2.gelfclient.GelfMessageBuilder; | ||
import org.graylog2.gelfclient.transport.GelfTransport; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
@EqualsAndHashCode | ||
public class GelfWriter extends OutputWriterAdapter { | ||
|
||
private static final Logger log = LoggerFactory.getLogger(GelfWriter.class); | ||
|
||
private final Map<String, Object> additionalFields; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Really minor... This map should probably be an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ImmutableMap maybe, but <String, Object> is correct, because JSON could contain integers or booleans. |
||
private final GelfTransport gelfTransport; | ||
private final ImmutableList<String> typeNames; | ||
|
||
public GelfWriter( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not absolutely required, but it would be nice if this class implements a meaningful equals and hashCode. Lombok can help. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 鉁旓笍 |
||
final ImmutableList<String> typeNames, | ||
final Map<String, Object> additionalFields, | ||
final GelfTransport gelfTransport | ||
) { | ||
this.typeNames = typeNames; | ||
this.additionalFields = additionalFields; | ||
this.gelfTransport = gelfTransport; | ||
} | ||
|
||
@Override | ||
public void doWrite(final Server server, final Query query, final Iterable<Result> results) | ||
throws Exception | ||
{ | ||
final GelfMessageBuilder messageBuilder = new GelfMessageBuilder( | ||
"", | ||
server.getHost() | ||
); | ||
|
||
final List<String> messages = new ArrayList<>(); | ||
|
||
for (final Result result : results) { | ||
log.debug("Query result: [{}]", result); | ||
for (final Map.Entry<String, Object> values : result.getValues() | ||
.entrySet()) { | ||
final String | ||
key = | ||
KeyUtils.getKeyString(query, result, values, this.typeNames); | ||
|
||
messages.add( | ||
String.format( | ||
"%s=%s", | ||
key, | ||
values.getValue() | ||
) | ||
); | ||
|
||
messageBuilder.additionalField(key, values.getValue()); | ||
} | ||
} | ||
|
||
if (additionalFields != null) { | ||
for (final Map.Entry<String, Object> additionalField : additionalFields | ||
.entrySet()) { | ||
messageBuilder.additionalField(additionalField.getKey(), | ||
additionalField.getValue()); | ||
} | ||
} | ||
|
||
final String message = StringUtils.join(messages, " "); | ||
|
||
messageBuilder.message(message); | ||
messageBuilder.fullMessage(message); | ||
|
||
log.debug( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 鉁旓笍 |
||
"Sending GELF message: {}", | ||
messageBuilder.build().toString() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like you are building the message twice. Storing it in a local variable would be nicer (I do expect that building this message is cheap, so this is not much of an optimization, feel free to ignore). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 鉁旓笍 |
||
); | ||
|
||
this.gelfTransport.send(messageBuilder.build()); | ||
} | ||
|
||
public Map<String, Object> getAdditionalFields() { | ||
return additionalFields; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
/** | ||
* The MIT License | ||
* Copyright 漏 2010 JmxTrans team | ||
* | ||
* Permission is hereby granted, free of charge, to any person obtaining a copy | ||
* of this software and associated documentation files (the "Software"), to deal | ||
* in the Software without restriction, including without limitation the rights | ||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
* copies of the Software, and to permit persons to whom the Software is | ||
* furnished to do so, subject to the following conditions: | ||
* | ||
* The above copyright notice and this permission notice shall be included in | ||
* all copies or substantial portions of the Software. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
* THE SOFTWARE. | ||
*/ | ||
package com.googlecode.jmxtrans.model.output.gelf; | ||
|
||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import com.google.common.collect.ImmutableList; | ||
import com.googlecode.jmxtrans.model.OutputWriterFactory; | ||
import lombok.EqualsAndHashCode; | ||
import org.graylog2.gelfclient.GelfConfiguration; | ||
import org.graylog2.gelfclient.GelfTransports; | ||
import org.graylog2.gelfclient.transport.GelfTransport; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import javax.annotation.Nonnull; | ||
import java.io.File; | ||
import java.util.Map; | ||
|
||
@EqualsAndHashCode | ||
public class GelfWriterFactory implements OutputWriterFactory { | ||
|
||
private final ImmutableList<String> typeNames; | ||
private final boolean booleanAsNumber; | ||
private final Boolean debugEnabled; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. debugEnabled and settings don't seem to be used. They should be removed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 鉁旓笍 |
||
private final Map<String, Object> settings; | ||
private final GelfConfiguration gelfConfiguration; | ||
private final Map<String, Object> additionalFields; | ||
private static final Logger log = LoggerFactory.getLogger(GelfWriter.class); | ||
|
||
public GelfWriterFactory( | ||
@JsonProperty("typeNames") final ImmutableList<String> typeNames, | ||
@JsonProperty("booleanAsNumber") final boolean booleanAsNumber, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. booleanAsNumber should be used by wrapping the generated OutputWriter in the appropriate transformer. There are some other OutputWriter that already use that. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I removed it as I was not using it. (Or should I use it?) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like |
||
@JsonProperty("debugEnabled") final Boolean debugEnabled, | ||
@JsonProperty("settings") final Map<String, Object> settings, | ||
@JsonProperty("host") final String host, | ||
@JsonProperty("port") final Integer port, | ||
@JsonProperty("additionalFields") | ||
final Map<String, Object> additionalFields, | ||
@JsonProperty("transport") final String transport, | ||
@JsonProperty("queueSize") final Integer queueSize, | ||
@JsonProperty("connectTimeout") final Integer connectTimeout, | ||
@JsonProperty("reconnectDelay") final Integer reconnectDelay, | ||
@JsonProperty("tcpNoDelay") final Boolean tcpNoDelay, | ||
@JsonProperty("sendBufferSize") final Integer sendBufferSize, | ||
@JsonProperty("tlsEnabled") final Boolean tlsEnabled, | ||
@JsonProperty("tlsTrustCertChainFile") | ||
final String tlsTrustCertChainFile, | ||
@JsonProperty("tlsCertVerificationEnabled") | ||
final Boolean tlsCertVerificationEnabled, | ||
@JsonProperty("tcpKeepAlive") final Boolean tcpKeepAlive, | ||
@JsonProperty("maxInflightSends") final Integer maxInflightSends | ||
) | ||
{ | ||
this.typeNames = typeNames; | ||
this.booleanAsNumber = booleanAsNumber; | ||
this.debugEnabled = debugEnabled; | ||
this.settings = settings; | ||
|
||
this.additionalFields = additionalFields; | ||
|
||
if (host == null) { | ||
throw new NullPointerException("Host can not be null"); | ||
} | ||
|
||
if (port != null) { | ||
this.gelfConfiguration = new GelfConfiguration(host, port); | ||
} else { | ||
this.gelfConfiguration = new GelfConfiguration(host); | ||
} | ||
|
||
if (transport != null) { | ||
final GelfTransports gelfTransports; | ||
|
||
switch (transport.toUpperCase()) { | ||
case "TCP": | ||
gelfTransports = GelfTransports.TCP; | ||
break; | ||
case "UDP": | ||
gelfTransports = GelfTransports.UDP; | ||
break; | ||
default: | ||
gelfTransports = GelfTransports.TCP; | ||
} | ||
|
||
gelfConfiguration.transport(gelfTransports); | ||
} | ||
|
||
if (queueSize != null) { | ||
gelfConfiguration.queueSize(queueSize); | ||
} | ||
|
||
if (connectTimeout != null) { | ||
gelfConfiguration.connectTimeout(connectTimeout); | ||
} | ||
|
||
if (reconnectDelay != null) { | ||
gelfConfiguration.reconnectDelay(reconnectDelay); | ||
} | ||
|
||
if (tcpNoDelay != null) { | ||
gelfConfiguration.tcpNoDelay(tcpNoDelay); | ||
} | ||
|
||
if (sendBufferSize != null) { | ||
gelfConfiguration.sendBufferSize(sendBufferSize); | ||
} | ||
|
||
if (tlsEnabled != null) { | ||
if (tlsEnabled) { | ||
gelfConfiguration.enableTls(); | ||
} else { | ||
gelfConfiguration.disableTls(); | ||
} | ||
} | ||
|
||
if (tlsCertVerificationEnabled != null) { | ||
if (tlsCertVerificationEnabled) { | ||
gelfConfiguration.enableTlsCertVerification(); | ||
} else { | ||
gelfConfiguration.disableTlsCertVerification(); | ||
} | ||
} | ||
|
||
if (tlsTrustCertChainFile != null) { | ||
gelfConfiguration.tlsTrustCertChainFile(new File( | ||
tlsTrustCertChainFile)); | ||
} | ||
|
||
if (tcpKeepAlive != null) { | ||
gelfConfiguration.tcpKeepAlive(tcpKeepAlive); | ||
} | ||
|
||
if (maxInflightSends != null) { | ||
gelfConfiguration.maxInflightSends(maxInflightSends); | ||
} | ||
|
||
log.debug("Created gelf configuration: {}", | ||
gelfConfiguration.toString()); | ||
|
||
} | ||
|
||
@Nonnull | ||
@Override | ||
public GelfWriter create() { | ||
final GelfTransport gelfTransport = GelfTransports.create( | ||
gelfConfiguration | ||
); | ||
|
||
return new GelfWriter( | ||
this.typeNames, | ||
this.additionalFields, | ||
gelfTransport | ||
); | ||
} | ||
|
||
public GelfConfiguration getGelfConfiguration() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This shoudl probably be marked as @VisibleForTesting. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, okay. 鉁旓笍 |
||
return gelfConfiguration; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you move version declaration to the parent pom? (in the dependencyManagement section)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
鉁旓笍