Skip to content

Commit c41e673

Browse files
committed
rework the way that datasource names are generated (again). hopefully this will be the last time.
fixed a bug where the results list wasn't being reset and thus growing infinitely based on the number of queries being executed. added another example for querying ActiveMQ. get all of the type name values that are requested.
1 parent 4472815 commit c41e673

10 files changed

+224
-129
lines changed

.classpath

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
<classpathentry kind="lib" path="lib/slf4j-log4j12-1.6.1.jar"/>
1515
<classpathentry kind="lib" path="lib/log4j-1.2.16.jar"/>
1616
<classpathentry kind="lib" path="lib/jpathwatch-0-93-rc1.jar"/>
17+
<classpathentry kind="lib" path="lib/commons-codec-1.3.jar" sourcepath="lib/commons-codec-1.3-sources.jar"/>
1718
<classpathentry kind="src" path="src"/>
1819
<classpathentry kind="output" path="_eclipse"/>
1920
</classpath>

heapmemory-rrd-template.xml

+8-28
Original file line numberDiff line numberDiff line change
@@ -5,34 +5,14 @@
55
<!-- not mandatory -->
66
<step>60</step>
77
<!-- at least one datasource must be supplied -->
8-
<datasource>
9-
<name>max</name>
10-
<type>GAUGE</type>
11-
<heartbeat>400</heartbeat>
12-
<min>U</min>
13-
<max>U</max>
14-
</datasource>
15-
<datasource>
16-
<name>committed</name>
17-
<type>GAUGE</type>
18-
<heartbeat>400</heartbeat>
19-
<min>U</min>
20-
<max>U</max>
21-
</datasource>
22-
<datasource>
23-
<name>init</name>
24-
<type>GAUGE</type>
25-
<heartbeat>400</heartbeat>
26-
<min>U</min>
27-
<max>U</max>
28-
</datasource>
29-
<datasource>
30-
<name>used</name>
31-
<type>GAUGE</type>
32-
<heartbeat>400</heartbeat>
33-
<min>U</min>
34-
<max>U</max>
35-
</datasource>
8+
<datasource><!-- type=Memory:HeapMemoryUsage:committed --><name>HeapMemoryUsagefd71</name><type>GAUGE</type><heartbeat>400</heartbeat><min>U</min><max>U</max></datasource>
9+
<datasource><!-- type=Memory:HeapMemoryUsage:init --><name>HeapMemoryUsage25f7</name><type>GAUGE</type><heartbeat>400</heartbeat><min>U</min><max>U</max></datasource>
10+
<datasource><!-- type=Memory:HeapMemoryUsage:max --><name>HeapMemoryUsageffe4</name><type>GAUGE</type><heartbeat>400</heartbeat><min>U</min><max>U</max></datasource>
11+
<datasource><!-- type=Memory:HeapMemoryUsage:used --><name>HeapMemoryUsaged3bb</name><type>GAUGE</type><heartbeat>400</heartbeat><min>U</min><max>U</max></datasource>
12+
<datasource><!-- type=Memory:NonHeapMemoryUsage:committed --><name>NHMUb93cabbe11008a2</name><type>GAUGE</type><heartbeat>400</heartbeat><min>U</min><max>U</max></datasource>
13+
<datasource><!-- type=Memory:NonHeapMemoryUsage:init --><name>NHMU0a2a437bb561de8</name><type>GAUGE</type><heartbeat>400</heartbeat><min>U</min><max>U</max></datasource>
14+
<datasource><!-- type=Memory:NonHeapMemoryUsage:max --><name>NHMU925cc6ce551095e</name><type>GAUGE</type><heartbeat>400</heartbeat><min>U</min><max>U</max></datasource>
15+
<datasource><!-- type=Memory:NonHeapMemoryUsage:used --><name>NHMU42f37e7c3e62970</name><type>GAUGE</type><heartbeat>400</heartbeat><min>U</min><max>U</max></datasource>
3616
<!-- at least one archive must be supplied -->
3717
<archive>
3818
<cf>AVERAGE</cf>

lib/commons-codec-1.3-sources.jar

54.3 KB
Binary file not shown.

lib/commons-codec-1.3.jar

45.6 KB
Binary file not shown.

memorypool-rrd-template.xml

+70-70
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package com.googlecode.jmxtrans.example;
2+
3+
import com.googlecode.jmxtrans.model.JmxProcess;
4+
import com.googlecode.jmxtrans.model.Query;
5+
import com.googlecode.jmxtrans.model.Server;
6+
import com.googlecode.jmxtrans.model.output.RRDToolWriter;
7+
import com.googlecode.jmxtrans.util.JmxUtils;
8+
9+
/**
10+
* This example shows how to query an ActiveMQ server for some information.
11+
*
12+
* The point of this example is to show that * works as part of the objectName.
13+
* It also shows that you don't have to set an attribute to get for a query.
14+
* jmxtrans will get all attributes on an object if you don't specify any.
15+
*
16+
* @author jon
17+
*/
18+
public class ActiveMQ2 {
19+
20+
/** */
21+
public static void main(String[] args) throws Exception {
22+
23+
Server server = new Server("w2", "1105");
24+
server.setAlias("w2_activemq_1105");
25+
RRDToolWriter gw = new RRDToolWriter();
26+
gw.addSetting(RRDToolWriter.TEMPLATE_FILE, "memorypool-rrd-template.xml");
27+
gw.addSetting(RRDToolWriter.OUTPUT_FILE, "target/w2-TEST.rrd");
28+
gw.addSetting(RRDToolWriter.BINARY_PATH, "/opt/local/bin");
29+
gw.addSetting(RRDToolWriter.DEBUG, "true");
30+
gw.addSetting(RRDToolWriter.GENERATE, "true");
31+
32+
// use this to add data to GW path
33+
gw.addTypeName("Destination");
34+
35+
Query q = new Query();
36+
q.setObj("org.apache.activemq:BrokerName=localhost,Type=Queue,Destination=*");
37+
q.addAttr("QueueSize");
38+
q.addAttr("MaxEnqueueTime");
39+
q.addAttr("MinEnqueueTime");
40+
q.addAttr("AverageEnqueueTime");
41+
q.addAttr("InFlightCount");
42+
q.addAttr("ConsumerCount");
43+
q.addAttr("ProducerCount");
44+
q.addAttr("DispatchCount");
45+
q.addAttr("DequeueCount");
46+
q.addAttr("EnqueueCount");
47+
q.addOutputWriter(gw);
48+
server.addQuery(q);
49+
50+
Query q2 = new Query();
51+
q2.setObj("org.apache.activemq:BrokerName=localhost,Type=Topic,Destination=*");
52+
q2.addAttr("QueueSize");
53+
q2.addAttr("MaxEnqueueTime");
54+
q2.addAttr("MinEnqueueTime");
55+
q2.addAttr("AverageEnqueueTime");
56+
q2.addAttr("InFlightCount");
57+
q2.addAttr("ConsumerCount");
58+
q2.addAttr("ProducerCount");
59+
q2.addAttr("DispatchCount");
60+
q2.addAttr("DequeueCount");
61+
q2.addAttr("EnqueueCount");
62+
q2.addOutputWriter(gw);
63+
server.addQuery(q2);
64+
65+
JmxProcess process = new JmxProcess(server);
66+
JmxUtils.prettyPrintJson(process);
67+
JmxUtils.processServer(server);
68+
69+
// for (int i = 0; i < 160; i++) {
70+
// JmxUtils.processServer(server);
71+
// Thread.sleep(1000);
72+
// }
73+
74+
}
75+
}

src/com/googlecode/jmxtrans/model/output/GraphiteWriter.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public void doWrite(Query query) throws Exception {
7474
sb.append(cleanupStr(r.getClassName()));
7575
sb.append(".");
7676

77-
String typeName = cleanupStr(retrieveTypeNameValue(r.getTypeName()));
77+
String typeName = cleanupStr(getConcatedTypeNameValues(r.getTypeName()));
7878
if (typeName != null) {
7979
sb.append(typeName);
8080
sb.append(".");

src/com/googlecode/jmxtrans/model/output/RRDToolWriter.java

+38-23
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import java.util.Map.Entry;
1111
import java.util.TreeMap;
1212

13+
import org.apache.commons.codec.digest.DigestUtils;
1314
import org.apache.commons.io.FileUtils;
1415
import org.apache.commons.lang.StringUtils;
1516
import org.apache.commons.lang.WordUtils;
@@ -42,9 +43,8 @@ public class RRDToolWriter extends BaseOutputWriter {
4243
private File outputFile = null;
4344
private File templateFile = null;
4445
private File binaryPath = null;
45-
private static final char[] PERIOD = {'.'};
46+
public static final String GENERATE = "generate";
4647
private static final char[] INITIALS = {' ', '.'};
47-
private static final String GENERATE = "generate";
4848

4949
/** */
5050
public RRDToolWriter() {
@@ -66,20 +66,24 @@ public void validateSetup() throws Exception {
6666
* well it seems.
6767
*/
6868
public String getDataSourceName(String typeName, String attributeName, String entry) {
69-
String typeNameClean = "";
69+
70+
String result = null;
7071
if (typeName != null) {
71-
typeNameClean = cleanupStr(typeName);
72-
}
73-
String caps = WordUtils.capitalize(typeNameClean + "." + attributeName, PERIOD);
74-
String[] split = StringUtils.splitByCharacterTypeCamelCase(caps);
75-
String join = StringUtils.join(split, '.');
76-
String result = WordUtils.initials(join, INITIALS);
77-
78-
if (result.length() + entry.length() < 21) {
79-
return result + WordUtils.capitalize(entry);
72+
result = typeName + attributeName + entry;
8073
} else {
81-
return result + WordUtils.initials(entry);
74+
result = attributeName + entry;
8275
}
76+
77+
if (attributeName.length() > 15) {
78+
String[] split = StringUtils.splitByCharacterTypeCamelCase(attributeName);
79+
String join = StringUtils.join(split, '.');
80+
attributeName = WordUtils.initials(join, INITIALS);
81+
}
82+
result = attributeName + DigestUtils.md5Hex(result);
83+
84+
result = StringUtils.left(result, 19);
85+
86+
return result;
8387
}
8488

8589
/** */
@@ -88,7 +92,7 @@ public void doWrite(Query query) throws Exception {
8892

8993
List<String> dsNames = getDsNames(def.getDsDefs());
9094
List<Result> results = query.getResults();
91-
95+
9296
Map<String, String> dataMap = new TreeMap<String, String>();
9397

9498
// go over all the results and look for datasource names that map to keys from the result values
@@ -97,7 +101,7 @@ public void doWrite(Query query) throws Exception {
97101
Map<String, Object> values = res.getValues();
98102
if (values != null) {
99103
for (Entry<String, Object> entry : values.entrySet()) {
100-
String key = getDataSourceName(retrieveTypeNameValue(res.getTypeName()), res.getAttributeName(), entry.getKey());
104+
String key = getDataSourceName(getConcatedTypeNameValues(res.getTypeName()), res.getAttributeName(), entry.getKey());
101105
boolean isNumeric = JmxUtils.isNumeric(entry.getValue());
102106

103107
if (isDebugEnabled() && isNumeric) {
@@ -111,28 +115,39 @@ public void doWrite(Query query) throws Exception {
111115
}
112116
}
113117

118+
doGenerate(results);
119+
120+
if (dataMap.keySet().size() > 0 && dataMap.values().size() > 0) {
121+
rrdToolUpdate(StringUtils.join(dataMap.keySet(), ':'), StringUtils.join(dataMap.values(), ':'));
122+
} else {
123+
log.error("Nothing was logged for query: " + query);
124+
}
125+
}
126+
127+
private void doGenerate(List<Result> results) throws Exception {
114128
if (isDebugEnabled() && this.getBooleanSetting(GENERATE)) {
115129
StringBuilder sb = new StringBuilder("\n");
130+
List<String> keys = new ArrayList<String>();
131+
116132
for (Result res : results) {
117133
Map<String, Object> values = res.getValues();
118134
if (values != null) {
119135
for (Entry<String, Object> entry : values.entrySet()) {
120136
boolean isNumeric = JmxUtils.isNumeric(entry.getValue());
121137
if (isNumeric) {
122-
String key = getDataSourceName(retrieveTypeNameValue(res.getTypeName()), res.getAttributeName(), entry.getKey());
123-
sb.append("<datasource><name>" + key + "</name><type>GAUGE</type><heartbeat>400</heartbeat><min>U</min><max>U</max></datasource>\n");
138+
String key = getDataSourceName(getConcatedTypeNameValues(res.getTypeName()), res.getAttributeName(), entry.getKey());
139+
if (keys.contains(key)) {
140+
throw new Exception("Duplicate datasource name found: '" + key + "'. Please try to add more typeName keys to the writer to make the name more unique. " + res.toString());
141+
}
142+
keys.add(key);
143+
144+
sb.append("<datasource><!-- " + res.getTypeName() + ":" + res.getAttributeName() + ":" + entry.getKey() + " --><name>" + key + "</name><type>GAUGE</type><heartbeat>400</heartbeat><min>U</min><max>U</max></datasource>\n");
124145
}
125146
}
126147
}
127148
}
128149
log.debug(sb.toString());
129150
}
130-
131-
if (dataMap.keySet().size() > 0 && dataMap.values().size() > 0) {
132-
rrdToolUpdate(StringUtils.join(dataMap.keySet(), ':'), StringUtils.join(dataMap.values(), ':'));
133-
} else {
134-
log.error("Nothing was logged for query: " + query);
135-
}
136151
}
137152

138153
/**

src/com/googlecode/jmxtrans/util/BaseOutputWriter.java

+27-5
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,23 @@ public void setSettings(Map<String, Object> settings) {
4747

4848
/** */
4949
public boolean getBooleanSetting(String key) {
50-
return this.getSettings().containsKey(key) ? (Boolean) this.getSettings().get(key) : Boolean.FALSE;
50+
Boolean result = null;
51+
if (this.getSettings().containsKey(key)) {
52+
Object foo = this.getSettings().get(key);
53+
if (foo instanceof String) {
54+
result = Boolean.valueOf((String)foo);
55+
} else if (foo instanceof Boolean) {
56+
result = (Boolean)foo;
57+
}
58+
}
59+
return result;
5160
}
5261

5362
/** */
5463
@JsonIgnore
5564
public boolean isDebugEnabled() {
5665
if (debugEnabled == null) {
57-
debugEnabled = this.getSettings().containsKey(DEBUG) ? (Boolean) this.getSettings().get(DEBUG) : Boolean.FALSE;
66+
return getBooleanSetting(DEBUG);
5867
}
5968
return debugEnabled != null ? debugEnabled : false;
6069
}
@@ -88,12 +97,25 @@ public void addTypeName(String str) {
8897
*
8998
* If you addTypeName("name"), then it'll retrieve 'PS Eden Space' from the string
9099
*/
91-
protected String retrieveTypeNameValue(String typeNameStr) {
100+
protected String getConcatedTypeNameValues(String typeNameStr) {
92101
List<String> typeNames = getTypeNames();
93102
if (typeNames == null || typeNames.size() == 0) {
94103
return null;
95104
}
96105
String[] tokens = typeNameStr.split(",");
106+
StringBuilder sb = new StringBuilder();
107+
for (String key : typeNames) {
108+
String result = getTypeNameValue(key, tokens);
109+
if (result != null) {
110+
sb.append(result);
111+
sb.append("_");
112+
}
113+
}
114+
return sb.toString();
115+
}
116+
117+
/** */
118+
private String getTypeNameValue(String typeName, String[] tokens) {
97119
boolean foundIt = false;
98120
for (String token : tokens) {
99121
String[] keys = token.split("=");
@@ -102,7 +124,7 @@ protected String retrieveTypeNameValue(String typeNameStr) {
102124
if (foundIt) {
103125
return key;
104126
}
105-
if (typeNames.contains(key)) {
127+
if (typeName.equals(key)) {
106128
foundIt = true;
107129
}
108130
}
@@ -117,7 +139,7 @@ protected String cleanupStr(String name) {
117139
if (name == null) {
118140
return null;
119141
}
120-
String clean = name.replace('.', '_');
142+
String clean = name.replace(".", "_");
121143
clean = clean.replace(" ", "");
122144
return clean;
123145
}

src/com/googlecode/jmxtrans/util/JmxUtils.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,13 @@ public void run() {
103103

104104
public static void processQuery(MBeanServerConnection mbeanServer, Query query) throws Exception {
105105

106-
List<Result> resList = new ArrayList<Result>();
107-
108106
ObjectName oName = new ObjectName(query.getObj());
109107

110108
Set<ObjectName> queryNames = mbeanServer.queryNames(oName, null);
111109
for (ObjectName queryName : queryNames) {
110+
111+
List<Result> resList = new ArrayList<Result>();
112+
112113
MBeanInfo info = mbeanServer.getMBeanInfo(queryName);
113114
ObjectInstance oi = mbeanServer.getObjectInstance(queryName);
114115

@@ -123,6 +124,7 @@ public static void processQuery(MBeanServerConnection mbeanServer, Query query)
123124
try {
124125
if (query.getAttr() != null && query.getAttr().size() > 0) {
125126
log.debug("Started query: " + query);
127+
126128
AttributeList al = mbeanServer.getAttributes(queryName, query.getAttr().toArray(new String[query.getAttr().size()]));
127129
for (Attribute attribute : al.asList()) {
128130
getResult(resList, info, oi, (Attribute)attribute, query);

0 commit comments

Comments
 (0)