diff --git a/build/build.xml b/build/build.xml index cdd8e52..566a78c 100644 --- a/build/build.xml +++ b/build/build.xml @@ -55,6 +55,7 @@ + @@ -100,4 +101,4 @@ - \ No newline at end of file + diff --git a/config/jmx.xml b/config/jmx.xml index dc8b8e3..cb08ebd 100644 --- a/config/jmx.xml +++ b/config/jmx.xml @@ -11,7 +11,7 @@ --> - + diff --git a/config/splunkagent.properties b/config/splunkagent.properties index 95b2d8d..ee75458 100644 --- a/config/splunkagent.properties +++ b/config/splunkagent.properties @@ -4,43 +4,74 @@ # Common Agent options #--------------------- -agent.app.name=MyTestApp -agent.app.instance=MyJVM -agent.userEventTags=key1=value1,key2=value2 +agent.app.name=myapp +agent.app.instance=myjvm +#agent.userEventTags=key1=value1,key2=value2 #------------------------- # Splunk Transport options #------------------------- #splunk.transport.internalQueueSize=10000 -splunk.transport.impl=com.splunk.javaagent.transport.SplunkTCPTransport + +splunk.transport.impl=com.splunk.javaagent.transport.SplunkRestTransport +splunk.transport.rest.host=10.0.0.67 +splunk.transport.rest.port=8089 +splunk.transport.rest.username=admin +splunk.transport.rest.password=password +splunk.transport.rest.scheme=https +splunk.transport.rest.index=main +splunk.transport.rest.sourcetype=SplunkJavaAgentSourceType +splunk.transport.rest.source=SplunkJavaAgentSource + #splunk.transport.impl=com.splunk.javaagent.transport.SplunkStdOutTransport -splunk.transport.tcp.host=your-splunk-server + +#begin tcp transport settings +#splunk.transport.impl=com.splunk.javaagent.transport.SplunkTCPTransport +splunk.transport.tcp.host=localhost splunk.transport.tcp.port=5150 -splunk.transport.tcp.maxQueueSize=5MB +splunk.transport.tcp.maxQueueSize=20MB splunk.transport.tcp.dropEventsOnQueueFull=false +#end tcp transport settings #----------------------------------- # Class/Method/Error Tracing options #----------------------------------- +#trace.whitelist=net/ #trace.whitelist=com/some/package/you/want/to/monitor -trace.blacklist=com/sun,sun/,java/,javax/,com/splunk/javaagent/ -trace.methodEntered=true -trace.methodExited=true -trace.classLoaded=true -trace.errors=true +#trace.blacklist=com/sun,sun/,java/,javax/,com/splunk/javaagent/ +#trace.blacklist=com/sun,sun/,java/,javax/,com/splunk/javaagent/,org/eclipse,org/osgi,org/apache/xerces +#trace.blacklist=com/sun,sun/,javax/,com/splunk/javaagent/,org/eclipse,org/osgi,org/apache/xerces +#trace.blacklist=com/splunk/javaagent/,org/apache/xerces,org/apache/juli +#trace.blacklist=com/splunk/javaagent/,org/apache/xerces +trace.blacklist=com/splunk/javaagent/,org/apache/juli/logging/DirectJDKLog +#trace.blacklist=com/splunk/javaagent/ +#trace.methodEntered=true + +#trace.methodEntered=true +#trace.methodExited=true +#trace.classLoaded=true +#trace.errors=true +trace.methodEntered=false +trace.methodExited=false +trace.classLoaded=false +trace.errors=false + #------------------------------ # HPROF Dump Collection options #------------------------------ #periodically dump hprof file(using JMX operation call), read in file & parse, send events to Splunk, delete file +#trace.hprof=false trace.hprof=false -trace.hprof.tempfile=mydump.hprof +trace.hprof.tempfile=/tmp/mydump.hprof #trace.hprof.tempfile=/etc/tmp/dump.hprof #in seconds -trace.hprof.frequency=600 +#trace.hprof.frequency=600 +trace.hprof.frequency=60 #trace.hprof.recordtypes=2,3,4 +#trace.hprof.recordtypes=2,3,4,5,6,7,10,11,12,28,44,13,14 #by default , all hprof records will be traced, but you can provide a comma delimited list of #specific record types to trace, the numbers are decimal values from the hprof spec. @@ -64,6 +95,7 @@ trace.hprof.frequency=600 #Heap dumps(codes 12 & 28) can have subrecords , so you can use ":" notation to reference these values #trace.hprof.recordtypes=12:1,12:32,12:33,12:34 +trace.hprof.recordtypes=1,2,3,4,5,6,7,10,11,12:1,12:32,12:33,12:34,28,44,13,14 #HEAPDUMP SUB RECORD TYPE CODE #========================================= @@ -86,10 +118,11 @@ trace.hprof.frequency=600 #-------------------------------------------------------- #Embedded JMX polling , all other JMX config is in the JMX XML configuration file. -trace.jmx=false +#trace.jmx=false +trace.jmx=true #name of XML files(minus the ".xml" suffix) that should reside in the root of splunkagent.jar trace.jmx.configfiles=jmx #trace.jmx.configfiles=goo,foo #in seconds trace.jmx.default.frequency=60 -#trace.jmx.goo.frequency=30 \ No newline at end of file +#trace.jmx.goo.frequency=30 diff --git a/lib/splunk-sdk-java-1.2.jar b/lib/splunk-sdk-java-1.2.jar new file mode 100644 index 0000000..72dbf4f Binary files /dev/null and b/lib/splunk-sdk-java-1.2.jar differ diff --git a/make.sh b/make.sh new file mode 100755 index 0000000..7399e4e --- /dev/null +++ b/make.sh @@ -0,0 +1,8 @@ +#!/bin/bash -x + +rm -rf ~/java/SplunkJavaAgent-master/releases/* +cd build +ant +cd ../moo +tar zxf /Users/travisfreeland/java/SplunkJavaAgent-master/releases/splunkagent.tar.gz +cp splunkagent/splunkagent.jar ~/java/splunkagent.jar diff --git a/moo/splunkagent/LICENSE b/moo/splunkagent/LICENSE new file mode 100644 index 0000000..e123bac --- /dev/null +++ b/moo/splunkagent/LICENSE @@ -0,0 +1,14 @@ +This work is licensed under the Creative Commons Attribution 3.0 Unported License. + +To view a copy of this license, visit : + +http://creativecommons.org/licenses/by/3.0/ + +Or send a letter to : + +Creative Commons, +444 Castro Street, +Suite 900, +Mountain View, +California, 94041, +USA. diff --git a/moo/splunkagent/splunkagent.jar b/moo/splunkagent/splunkagent.jar new file mode 100644 index 0000000..ba94f14 Binary files /dev/null and b/moo/splunkagent/splunkagent.jar differ diff --git a/releases/splunkagent.tar.gz b/releases/splunkagent.tar.gz index 885568d..deb9ece 100644 Binary files a/releases/splunkagent.tar.gz and b/releases/splunkagent.tar.gz differ diff --git a/rsync.sh b/rsync.sh new file mode 100755 index 0000000..2af16c3 --- /dev/null +++ b/rsync.sh @@ -0,0 +1,3 @@ +#!/bin/bash -x + +rsync -WIav --size-only --exclude RCS /Users/travisfreeland/java/SplunkJavaAgent-master/* . diff --git a/search.txt b/search.txt new file mode 100644 index 0000000..13be452 --- /dev/null +++ b/search.txt @@ -0,0 +1,3 @@ +index="splunkjavaagent" | transaction appName className methodName startswith="method_entered" endswith="method_exited" | rex max_match=0 "(?P\d+)\sname=" +| eval duration=tonumber(mvindex(method_time, 0))-tonumber(mvindex(method_time, 1)) +| timechart perc90(duration) by methodName diff --git a/src/com/splunk/javaagent/SplunkJavaAgent.java b/src/com/splunk/javaagent/SplunkJavaAgent.java index c8fec7a..ba9bf8c 100644 --- a/src/com/splunk/javaagent/SplunkJavaAgent.java +++ b/src/com/splunk/javaagent/SplunkJavaAgent.java @@ -188,9 +188,21 @@ private boolean initJMX() { return true; } - private boolean initCommonProperties() { + private boolean initCommonProperties() throws IOException { + + //this.appName = props.getProperty("agent.app.name", ""); + //this.appName = new Exception().fillInStackTrace().getStackTrace()[0].getClassName(); + + //make the name the PID + //http://blog.igorminar.com/2007/03/how-java-application-can-discover-its.html + byte[] bo = new byte[100]; + String[] cmd = {"bash", "-c", "echo $PPID"}; + Process p = Runtime.getRuntime().exec(cmd); + p.getInputStream().read(bo); + double d = Double.parseDouble(new String(bo)); + int di = (int) d; + this.appName = String.valueOf(di); - this.appName = props.getProperty("agent.app.name", ""); this.appID = props.getProperty("agent.app.instance", ""); String tags = (String) props.getProperty("agent.userEventTags", ""); @@ -536,15 +548,15 @@ public static void methodEntered(String className, String methodName, event.addPair("methodDesc", desc); event.addPair("threadID", Thread.currentThread().getId()); event.addPair("threadName", Thread.currentThread().getName()); - + try { StackTraceElement ste = Thread.currentThread().getStackTrace()[3]; - if(ste != null) - event.addPair("lineNumber", ste.getLineNumber()); - event.addPair("sourceFileName", ste.getFileName()); + if (ste != null) + event.addPair("lineNumber", ste.getLineNumber()); + event.addPair("sourceFileName", ste.getFileName()); } catch (Exception e1) { } - + addUserTags(event); try { agent.eventQueue.put(event); diff --git a/src/com/splunk/javaagent/SplunkLogEvent.java b/src/com/splunk/javaagent/SplunkLogEvent.java index c7b18c2..7383786 100644 --- a/src/com/splunk/javaagent/SplunkLogEvent.java +++ b/src/com/splunk/javaagent/SplunkLogEvent.java @@ -66,7 +66,7 @@ public class SplunkLogEvent { /** * Event prefix fields */ - private static final String PREFIX_NAME = "name"; + private static final String PREFIX_NAME = "SplunkJavaAgent_name"; private static final String PREFIX_EVENT_ID = "event_id"; /** @@ -1360,6 +1360,13 @@ private void addThrowableObject(Throwable throwable, int stackTraceDepth) { */ public void addPair(String key, String value) { + //convert ', ' to ',' + key = key.replaceAll(", ", ","); + value = value.replaceAll(", ", ","); + //convert spaces to underscores + key = key.replaceAll(" ", "_"); + value = value.replaceAll(" ", "_"); + if (quoteValues) this.eventMessage.append(key).append(KVDELIM).append(QUOTE) .append(value).append(QUOTE).append(PAIRDELIM); diff --git a/src/com/splunk/javaagent/jmx/ProcessServerThread.java b/src/com/splunk/javaagent/jmx/ProcessServerThread.java index e208ad1..be62ef7 100644 --- a/src/com/splunk/javaagent/jmx/ProcessServerThread.java +++ b/src/com/splunk/javaagent/jmx/ProcessServerThread.java @@ -11,9 +11,11 @@ import javax.management.NotificationFilter; import javax.management.ObjectInstance; import javax.management.ObjectName; -import javax.management.openmbean.CompositeDataSupport; +import javax.management.openmbean.CompositeData; + import javax.management.openmbean.CompositeType; -import javax.management.openmbean.TabularDataSupport; +import javax.management.openmbean.TabularData; + import com.splunk.javaagent.SplunkLogEvent; import com.splunk.javaagent.jmx.config.Attribute; @@ -136,9 +138,10 @@ public void run() { .getOutputname(); if (outputname != null && !outputname.isEmpty()) - mBeanAttributes.put( - operation.getOutputname(), - resolveObjectToString(result)); + //mBeanAttributes.put(operation + //.getOutputname(), + //resolveObjectToString(result)); + extractAttributeValue(result,mBeanAttributes,operation.getOutputname()); } catch (Exception e) { // logger.error("Error : " + @@ -178,7 +181,7 @@ else if (bean.getAttributes() != null) { // if the attribute pattern is multi level, loop // through the levels until the value is found for (String token : tokens) { - + // get root attribute object the first time if (attributeValue == null) { try { @@ -191,22 +194,25 @@ else if (bean.getAttributes() != null) { // logger.error("Error : " // + e.getMessage()); } - } else if (attributeValue instanceof CompositeDataSupport) { + } else if (attributeValue instanceof CompositeData) { try { - - attributeValue = ((CompositeDataSupport) attributeValue) + + attributeValue = ((CompositeData) attributeValue) .get(token); + + } catch (Exception e) { + e.printStackTrace(); // logger.error("Error : " // + e.getMessage()); } - } else if (attributeValue instanceof TabularDataSupport) { + } else if (attributeValue instanceof TabularData) { try { Object[] key = { token }; - attributeValue = ((TabularDataSupport) attributeValue) + attributeValue = ((TabularData) attributeValue) .get(key); } catch (Exception e) { @@ -214,11 +220,12 @@ else if (bean.getAttributes() != null) { // logger.error("Error : " // + e.getMessage()); } - } else { - + } + else { + } } - + mBeanAttributes.put(singular.getOutputname(), resolveObjectToString(attributeValue)); @@ -297,10 +304,10 @@ private void extractAttributeValue(Object attributeValue, // logger.error("Error : " + e.getMessage()); } - } else if (attributeValue instanceof CompositeDataSupport) { + } else if (attributeValue instanceof CompositeData) { try { - CompositeDataSupport cds = ((CompositeDataSupport) attributeValue); + CompositeData cds = ((CompositeData) attributeValue); CompositeType ct = cds.getCompositeType(); Set keys = ct.keySet(); @@ -314,10 +321,10 @@ private void extractAttributeValue(Object attributeValue, // logger.error("Error : " + e.getMessage()); } - } else if (attributeValue instanceof TabularDataSupport) { + } else if (attributeValue instanceof TabularData) { try { - TabularDataSupport tds = ((TabularDataSupport) attributeValue); - Set keys = tds.keySet(); + TabularData tds = ((TabularData) attributeValue); + Set keys = tds.keySet(); for (Object key : keys) { Object keyName = ((List) key).get(0); diff --git a/src/com/splunk/javaagent/transport/SplunkRestTransport.java b/src/com/splunk/javaagent/transport/SplunkRestTransport.java new file mode 100644 index 0000000..692b501 --- /dev/null +++ b/src/com/splunk/javaagent/transport/SplunkRestTransport.java @@ -0,0 +1,109 @@ +package com.splunk.javaagent.transport; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.net.Socket; +import java.util.Map; + +import com.splunk.javaagent.SplunkLogEvent; + +public class SplunkRestTransport extends SplunkInput implements SplunkTransport { + + // connection props + private String host = ""; + private int port; + private String username = ""; + private String password = ""; + private String scheme = ""; + + /* + splunk.transport.impl=com.splunk.javaagent.transport.SplunkRestTransport + splunk.transport.rest.host=10.0.0.67 + splunk.transport.rest.port=8089 + splunk.transport.rest.username=admin + splunk.transport.rest.password=password + splunk.transport.rest.scheme=https + splunk.transport.rest.index=main + splunk.transport.rest.sourcetype=SplunkJavaAgentSourceType + splunk.transport.rest.source=SplunkJavaAgentSource + */ + + // streaming objects + private Socket streamSocket = null; + private OutputStream ostream; + private Writer writerOut = null; + + @Override + public void init(Map args) throws Exception { + + this.host = args.get("splunk.transport.rest.host"); + this.port = Integer.parseInt(args.get("splunk.transport.rest.port")); + setDropEventsOnQueueFull(Boolean.parseBoolean(args + .get("splunk.transport.rest.dropEventsOnQueueFull"))); + setMaxQueueSize(args.get("splunk.transport.rest.maxQueueSize")); + } + + @Override + public void start() throws Exception { + streamSocket = new Socket(host, port); + if (streamSocket.isConnected()) { + ostream = streamSocket.getOutputStream(); + writerOut = new OutputStreamWriter(ostream, "UTF8"); + } + + } + + @Override + public void stop() throws Exception { + try { + + if (writerOut != null) { + writerOut.flush(); + writerOut.close(); + if (streamSocket != null) + streamSocket.close(); + } + } catch (Exception e) { + } + + } + + @Override + public void send(SplunkLogEvent event) { + String currentMessage = event.toString(); + try { + + if (writerOut != null) { + + // send the message + writerOut.write(currentMessage + "\n"); + + // flush the queue + while (queueContainsEvents()) { + String messageOffQueue = dequeue(); + currentMessage = messageOffQueue; + writerOut.write(currentMessage + "\n"); + } + writerOut.flush(); + } + + } catch (IOException e) { + + // something went wrong , put message on the queue for retry + enqueue(currentMessage); + try { + stop(); + } catch (Exception e1) { + } + + try { + start(); + } catch (Exception e2) { + } + } + + } + +}