Skip to content

Commit

Permalink
Merge pull request #330 from Microsoft/features/agent-automatic-addin…
Browse files Browse the repository at this point in the history
…g-of-builtin-classes

Way to add simple built in classes and MuleESB
  • Loading branch information
gupele authored Sep 18, 2016
2 parents d3a005f + d771c6a commit 450c7d7
Show file tree
Hide file tree
Showing 6 changed files with 289 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

package com.microsoft.applicationinsights.agent.internal.agent;

import java.util.Collection;
import java.util.Map;
import java.util.HashSet;
import java.util.Arrays;
Expand Down Expand Up @@ -89,9 +90,14 @@ public void setConfiguration(AgentConfiguration agentConfiguration) {
if (agentConfiguration.getBuiltInConfiguration().getDataOfConfigurationForException().isEnabled()) {
new RuntimeExceptionProvider(classesToInstrument).add();
}

addConfigurationData(agentConfiguration.getBuiltInConfiguration().getSimpleBuiltInClasses());
}

addConfigurationData(agentConfiguration);
Collection<ClassInstrumentationData> requestedClsssesToInstrument = agentConfiguration.getRequestedClassesToInstrument().values();
addConfigurationData(requestedClsssesToInstrument);

excludedPaths.addAll(agentConfiguration.getExcludedPrefixes());
}

/**
Expand Down Expand Up @@ -119,25 +125,20 @@ private boolean isExcluded(String className) {
return false;
}

private void addConfigurationData(AgentConfiguration agentConfiguration) {
if (agentConfiguration == null) {
private void addConfigurationData(Collection<ClassInstrumentationData> requestedClassesToInstrument) {
if (requestedClassesToInstrument == null) {
return;
}

Map<String, ClassInstrumentationData> configurationData = agentConfiguration.getRequestedClassesToInstrument();
if (configurationData != null) {
for (ClassInstrumentationData classInstrumentationData : configurationData.values()) {
if (isExcluded(classInstrumentationData.getClassName())) {
InternalAgentLogger.INSTANCE.trace("'%s' is not added since it is not allowed", classInstrumentationData.getClassName());
continue;
}

InternalAgentLogger.INSTANCE.trace("Adding '%s'", classInstrumentationData.getClassName());
classesToInstrument.put(classInstrumentationData.getClassName(), classInstrumentationData);
for (ClassInstrumentationData classInstrumentationData : requestedClassesToInstrument) {
if (isExcluded(classInstrumentationData.getClassName())) {
InternalAgentLogger.INSTANCE.trace("'%s' is not added since it is not allowed", classInstrumentationData.getClassName());
continue;
}
}

excludedPaths.addAll(agentConfiguration.getExcludedPrefixes());
InternalAgentLogger.INSTANCE.trace("Adding '%s'", classInstrumentationData.getClassName());
classesToInstrument.put(classInstrumentationData.getClassName(), classInstrumentationData);
}
}

private void setBuiltInDataFlag(AgentConfiguration agentConfiguration) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@

package com.microsoft.applicationinsights.agent.internal.config;

import com.microsoft.applicationinsights.agent.internal.agent.ClassInstrumentationData;

import java.util.List;

/**
* Created by gupele on 6/5/2015.
*/
Expand All @@ -34,15 +38,18 @@ public class AgentBuiltInConfiguration {
private final long maxSqlQueryLimitInMS;
private final long redisThresholdInMS;
private final DataOfConfigurationForException dataOfConfigurationForException;
private final List<ClassInstrumentationData> simpleBuiltInClasses;

public AgentBuiltInConfiguration(boolean httpEnabled,
public AgentBuiltInConfiguration(List<ClassInstrumentationData> simpleBuiltInClasses,
boolean httpEnabled,
boolean jdbcEnabled,
boolean hibernateEnabled,
boolean jedisEnabled,
boolean jmxEnabled,
Long maxSqlQueryLimitInMS,
long redisThresholdInMS,
DataOfConfigurationForException dataOfConfigurationForException) {
this.simpleBuiltInClasses = simpleBuiltInClasses;
this.enabled = true;
this.httpEnabled = httpEnabled;
this.jdbcEnabled = jdbcEnabled;
Expand Down Expand Up @@ -92,4 +99,8 @@ public boolean isJmxEnabled() {
public DataOfConfigurationForException getDataOfConfigurationForException() {
return dataOfConfigurationForException;
}

public List<ClassInstrumentationData> getSimpleBuiltInClasses() {
return simpleBuiltInClasses;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@

package com.microsoft.applicationinsights.agent.internal.config;

import com.microsoft.applicationinsights.agent.internal.agent.ClassInstrumentationData;

import java.util.List;

/**
* Created by gupele on 6/5/2015.
*/
Expand All @@ -34,13 +38,15 @@ public class AgentBuiltInConfigurationBuilder {
private long jedisThresholdInMS = 10000L;
private Long maxSqlQueryLimitInMS = 10000L;
private DataOfConfigurationForException dataOfConfigurationForException = new DataOfConfigurationForException();
private List<ClassInstrumentationData> simpleBuiltInClasses;

public AgentBuiltInConfiguration create() {
if (!enabled) {
this.dataOfConfigurationForException.setEnabled(false);
}

return new AgentBuiltInConfiguration(httpEnabled && enabled,
return new AgentBuiltInConfiguration(simpleBuiltInClasses,
httpEnabled && enabled,
jdbcEnabled && enabled,
hibernateEnabled && enabled,
hibernateEnabled && jedisEnabled,
Expand Down Expand Up @@ -95,4 +101,8 @@ public void setDataOfConfigurationForException(DataOfConfigurationForException d
this.dataOfConfigurationForException = dataOfConfigurationForException;
}
}

public void setSimpleBuiltInClasses(List<ClassInstrumentationData> simpleBuiltInClasses) {
this.simpleBuiltInClasses = simpleBuiltInClasses;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
/*
* ApplicationInsights-Java
* Copyright (c) Microsoft Corporation
* All rights reserved.
*
* MIT License
* 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.microsoft.applicationinsights.agent.internal.config;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.microsoft.applicationinsights.agent.internal.agent.ClassInstrumentationData;
import com.microsoft.applicationinsights.agent.internal.coresync.InstrumentedClassType;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

/**
* This class lets us add classes that will be a part of the 'BuiltIn' section in the AI-Agent.xml.
*
* This BuiltIn secion declares the classes and methods that the agent will instrument automatically.
*
* To add a new class you need to declare the XML tag for that class, which can be used by the user to
* either disable it, or change the threshold in which telemetries are sent for its instrumented methods.
*
* To add a new class you can do one of the following:
*
* <code>
* // Start define new class
* builtInInstrumentedClasses.put(
* // The XML tag in AI-Agent.xml (in the 'BuiltIn' section)
* "NewClassLogicalName",
*
* new BuiltInInstrumentedClass(
* // Full class name
* "an.example.of.full.class.path.to.RelevantClass",
*
* // All methods to instrument
* "method1", "method2"));
*
* </code>
*
* or (no method define, all methods will be instrumented)
* <code>
* // Start define new class
* builtInInstrumentedClasses.put(
* // The XML tag in AI-Agent.xml (in the 'BuiltIn' section)
* "NewClassLogicalName",
*
* new BuiltInInstrumentedClass(
* // Full class name
* "an.example.of.full.class.path.to.RelevantClass"));
*
* </code>
*
* or (set threshold in MS. Methods that will pass this threshold will be reported)
* <code>
* // Start define new class
* builtInInstrumentedClasses.put(
* // The XML tag in AI-Agent.xml (in the 'BuiltIn' section)
* "NewClassLogicalName",
*
* new BuiltInInstrumentedClass(
* // Full class name
* "an.example.of.full.class.path.to.RelevantClass", 100L));
*
* </code>
*
* To disable the class from being instrumented you now need to go to the AI-Agent.xml and:
*
* <code>
* <BuiltIn>
*
* <NewClassLogicalName enabled="false"/>
*
* </BuiltIn>
* </code>
*
* To change the class threshold:
*
* <code>
* <BuiltIn>
*
* <NewClassLogicalName thresholdInMS="10001"/>
*
* </BuiltIn>
* </code>
*
* Created by gupele on 8/2/2016.
*/
final class BuiltInInstrumentedClasses {

public static class BuiltInInstrumentedClass {
private final String className;
private final long thresholdInMS;
private ArrayList<String> methods;

public BuiltInInstrumentedClass(String className) {
this(className, 0, null);
}

public BuiltInInstrumentedClass(String className, long thresholdInMS) {
this(className, thresholdInMS, null);
}

public BuiltInInstrumentedClass(String className, String... methods) {
this(className, 0, methods);
}

public BuiltInInstrumentedClass(String className, long thresholdInMS, String... methods) {
this.className = className.replace(".", "/");
this.thresholdInMS = thresholdInMS;
this.methods = new ArrayList<String>();
if (methods != null) {
for (String method : methods){
this.methods.add(method);
}
}
}

public String getClassName() {
return className;
}

public List<String> getMethods() {
return methods;
}

public long getThresholdInMS() {
return thresholdInMS;
}
}

// Add the needed built in classes and methods
private static final Map<String, BuiltInInstrumentedClass> builtInInstrumentedClasses;
static
{
builtInInstrumentedClasses = new HashMap<String, BuiltInInstrumentedClass>();

// Mule ESB 3.3.0
builtInInstrumentedClasses.put(
// The XML tag in AI-Agent.xml (in the 'BuiltIn' section)
"MuleESB",

new BuiltInInstrumentedClass(
// Full class name
"org.mule.module.client.MuleClient",

// All methods to instrument
"dispatch", "send", "sendAsync", "sendDirect", "sendDirectAsync", "request"));
}

public Map<String, BuiltInInstrumentedClass> getBuiltInInstrumentedClasses() {
return builtInInstrumentedClasses;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* ApplicationInsights-Java
* Copyright (c) Microsoft Corporation
* All rights reserved.
*
* MIT License
* 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.microsoft.applicationinsights.agent.internal.config;

import com.microsoft.applicationinsights.agent.internal.agent.ClassInstrumentationData;
import com.microsoft.applicationinsights.agent.internal.coresync.InstrumentedClassType;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
* Created by gupele on 9/5/2016.
*/
public class BuiltInInstrumentedClassesBuilder {
private static final String THRESHOLD_ATTRIBUTE = "Threshold";

/**
* The method will go through the classes defined in {@link BuiltInInstrumentedClasses}
* and will try to add them and the methods that are define for them to the instrumentation classes
* @param builtInConfigurationBuilder - The builder that will later build the reflection of the configuration
* @param builtInElement - The built in element where built in instrumentation is declared
*/
public static void setSimpleBuiltInClasses(AgentBuiltInConfigurationBuilder builtInConfigurationBuilder, Element builtInElement) {
List<ClassInstrumentationData> classes = new ArrayList<ClassInstrumentationData>();
Map<String, BuiltInInstrumentedClasses.BuiltInInstrumentedClass> classicBuiltIns = new BuiltInInstrumentedClasses().getBuiltInInstrumentedClasses();
for (Map.Entry<String, BuiltInInstrumentedClasses.BuiltInInstrumentedClass> toInstrument : classicBuiltIns.entrySet()) {
NodeList nodes = builtInElement.getElementsByTagName(toInstrument.getKey());
boolean isEnabled = XmlParserUtils.getEnabled(XmlParserUtils.getFirst(nodes), toInstrument.getKey());
if (!isEnabled) {
continue;
}

BuiltInInstrumentedClasses.BuiltInInstrumentedClass classPredefinedData = toInstrument.getValue();

Element builtInTagElement = XmlParserUtils.getFirst(nodes);
long threshold = XmlParserUtils.getLongAttribute(builtInTagElement, toInstrument.getKey(), THRESHOLD_ATTRIBUTE, classPredefinedData.getThresholdInMS());
ClassInstrumentationData data = new ClassInstrumentationData(classPredefinedData.getClassName(), InstrumentedClassType.OTHER);
data.setThresholdInMS(threshold);

List<String> methods = classPredefinedData.getMethods();
if (methods == null) {
data.addAllMethods(false, true);
} else {
for (String method : methods) {
data.addMethod(method, "", false, true, threshold);
}
}

classes.add(data);
}
builtInConfigurationBuilder.setSimpleBuiltInClasses(classes);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ private void setBuiltInInstrumentation(AgentConfigurationDefaultImpl agentConfig
nodes = builtInElement.getElementsByTagName(MAX_STATEMENT_QUERY_LIMIT_TAG);
builtInConfigurationBuilder.setSqlMaxQueryLimitInMS(XmlParserUtils.getLong(XmlParserUtils.getFirst(nodes), MAX_STATEMENT_QUERY_LIMIT_TAG));

new BuiltInInstrumentedClassesBuilder().setSimpleBuiltInClasses(builtInConfigurationBuilder, builtInElement);

agentConfiguration.setBuiltInData(builtInConfigurationBuilder.create());
}

Expand Down

0 comments on commit 450c7d7

Please sign in to comment.