New feature: disabling instrumentations
MODIFY
dd-java-agent/Readme.md
dd-java-agent/Readme.md
@@ -72,9 +72,17 @@ sampler:
# RateSample: only a portion of spans are reported to the writer
# - Param 'rate': the portion of spans to keep
type: AllSampler
+ # Skip some traces if the root span tag values matches some regexp patterns
+ # skipTagsPatterns: {"http.url": ".*/demo/add.*"}
+
+# Enable custom tracing (Custom annotations for now)
+enableCustomTracing: true
+
+# Disable some instrumentations
+# disabledInstrumentations: ["apache http", "mongo", "jetty", "tomcat", ...]
```
-If you want to change it, you should then create it in your project and change it as suited.
+If you want to change it, you must create it in your project.
## Instrumented frameworks
@@ -114,6 +122,21 @@ But unfortunately this can not be done entirely automatically today. To enable t
We also provide an [example project with Spring Boot & MySQL](web application frameworks).
+### Disabling instrumentations
+
+If for some reasons you need to disable an instrumentation you should uncomment the `disabledInstrumentations: ` attribute in the configuration and provide a list as illustrated below:
+
+```yaml
+...
+
+# Disable a few instrumentations
+disabledInstrumentations: ["apache http", "mongo", "tomcat"]
+
+...
+```
+
+###
+
## Custom instrumentations
### The `@trace` annotation

MODIFY
dd-java-agent/src/main/java/com/datadoghq/trace/resolver/AgentTracerConfig.java
dd-java-agent/src/main/java/com/datadoghq/trace/resolver/AgentTracerConfig.java
package com.datadoghq.trace.resolver;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Configuration POJO for the agent
*/
@@ -7,6 +10,16 @@ public class AgentTracerConfig extends TracerConfig {
private boolean enableCustomTracing = false;
+ private List<String> disabledInstrumentations = new ArrayList<String>();
+
+ public List<String> getDisabledInstrumentations() {
+ return disabledInstrumentations;
+ }
+
+ public void setDisabledInstrumentations(List<String> uninstallContributions) {
+ this.disabledInstrumentations = uninstallContributions;
+ }
+
public boolean isEnableCustomTracing() {
return enableCustomTracing;
}

MODIFY
dd-java-agent/src/main/java/io/opentracing/contrib/agent/TraceAnnotationsManager.java
dd-java-agent/src/main/java/io/opentracing/contrib/agent/TraceAnnotationsManager.java
package io.opentracing.contrib.agent;
+import java.io.IOException;
+import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Method;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import org.jboss.byteman.agent.Location;
import org.jboss.byteman.agent.LocationType;
@@ -31,11 +42,13 @@ import javassist.bytecode.Descriptor;
*
* It loads all the scripts contained in all the 'oatrules.btm' resource files then instrument all the methods annoted with the @Trace.
*/
-public class TraceAnnotationsManager extends OpenTracingManager{
+public class TraceAnnotationsManager {
private static Logger log = Logger.getLogger(TraceAnnotationsManager.class.getName());
private static Retransformer transformer;
+ private static final String AGENT_RULES = "otarules.btm";
+
/**
* This method initializes the manager.
*
@@ -44,24 +57,57 @@ public class TraceAnnotationsManager extends OpenTracingManager{
*/
public static void initialize(Retransformer trans) throws Exception {
transformer = trans;
- OpenTracingManager.initialize(trans);
- OpenTracingManager.loadRules(ClassLoader.getSystemClassLoader());
-
//Load configuration
AgentTracerConfig agentTracerConfig = FactoryUtils.loadConfigFromResource(DDTracerFactory.CONFIG_PATH, AgentTracerConfig.class);
+ List<String> loadedScripts = loadRules(ClassLoader.getSystemClassLoader());
+
+ //Check if some rules have to be uninstalled
+ if(agentTracerConfig != null){
+ List<String> uninstallContributions = agentTracerConfig.getDisabledInstrumentations();
+ if(uninstallContributions!=null && !uninstallContributions.isEmpty()){
+ uninstallScripts(loadedScripts,uninstallContributions);
+ }
+ }
+
//Check if annotations are enabled
- if(agentTracerConfig.isEnableCustomTracing()){
- loadRules(ClassLoader.getSystemClassLoader());
+ if(agentTracerConfig != null && agentTracerConfig.isEnableCustomTracing()){
+ loadAnnotationsRules(ClassLoader.getSystemClassLoader());
+ }
+ }
+
+ /**
+ * Uninstall some scripts from a list of patterns.
+ * All the rules that contain the pattern will be uninstalled
+ *
+ * @param installedScripts
+ * @param patterns not case sensitive (eg. "mongo", "apache http", "elasticsearch", etc...])
+ */
+ public static void uninstallScripts(List<String> installedScripts, List<String> patterns) throws Exception{
+ Set<String> rulesToRemove = new HashSet<String>();
+
+ for(String strPattern : patterns){
+ Pattern pattern = Pattern.compile("(?i)RULE [^\n]*"+strPattern+"[^\n]*\n");
+ for(String loadedScript : installedScripts){
+ Matcher matcher = pattern.matcher(loadedScript);
+ while(matcher.find()){
+ rulesToRemove.add(matcher.group());
+ }
}
}
+ StringWriter sw = new StringWriter();
+ try(PrintWriter pr = new PrintWriter(sw)){
+ transformer.removeScripts(new ArrayList<String>(rulesToRemove), pr);
+ }
+ log.log(Level.INFO, sw.toString());
+ }
/**
* Find all the methods annoted with @Trace and inject rules
*
* @param classLoader
*/
- public static void loadRules(ClassLoader classLoader) {
+ public static void loadAnnotationsRules(ClassLoader classLoader) {
Reflections reflections = new Reflections(new ConfigurationBuilder()
.forPackages("/")
.filterInputsBy(new FilterBuilder().include(".*\\.class"))
@@ -140,6 +186,67 @@ public class TraceAnnotationsManager extends OpenTracingManager{
return ruleScript;
}
+ /**
+ * This method loads any OpenTracing Agent rules (otarules.btm) found as resources
+ * within the supplied classloader.
+ *
+ * @param classLoader The classloader
+ */
+ public static List<String> loadRules(ClassLoader classLoader) {
+ List<String> scripts = new ArrayList<>();
+ if (transformer == null) {
+ log.severe("Attempt to load OpenTracing agent rules before transformer initialized");
+ return scripts;
+ }
+
+ List<String> scriptNames = new ArrayList<>();
+
+ // Load default and custom rules
+ try {
+ Enumeration<URL> iter = classLoader.getResources(AGENT_RULES);
+ while (iter.hasMoreElements()) {
+ loadRules(iter.nextElement().toURI(), scriptNames, scripts);
+ }
+
+ StringWriter sw=new StringWriter();
+ try (PrintWriter writer = new PrintWriter(sw)) {
+ try {
+ transformer.installScript(scripts, scriptNames, writer);
+ } catch (Exception e) {
+ log.log(Level.SEVERE, "Failed to install scripts", e);
+ }
+ }
+ if (log.isLoggable(Level.FINEST)) {
+ log.finest(sw.toString());
+ }
+ } catch (IOException | URISyntaxException e) {
+ log.log(Level.SEVERE, "Failed to load OpenTracing agent rules", e);
+ }
+
+ if (log.isLoggable(Level.FINE)) {
+ log.fine("OpenTracing Agent rules loaded");
+ }
+ return scripts;
+ }
+
+ private static void loadRules(URI uri, final List<String> scriptNames,
+ final List<String> scripts) throws IOException {
+ if (log.isLoggable(Level.FINE)) {
+ log.fine("Load rules from URI = " + uri);
+ }
+
+ StringBuilder str=new StringBuilder();
+ try (InputStream is = uri.toURL().openStream()) {
+ byte[] b = new byte[10240];
+ int len;
+ while ((len = is.read(b)) != -1) {
+ str.append(new String(b, 0, len));
+ }
+ }
+ scripts.add(str.toString());
+ scriptNames.add(uri.toString());
+ }
+
private static String CURRENT_SPAN_EXISTS = "IF currentSpan() != null\n";
private static String CURRENT_SPAN_NOT_EXISTS = "IF currentSpan() == null\n";

MODIFY
dd-java-agent/src/main/resources/dd-trace.yaml
dd-java-agent/src/main/resources/dd-trace.yaml
@@ -19,6 +19,11 @@ sampler:
# RateSample: only a portion of spans are reported to the writer
# - Param 'rate': the portion of spans to keep
type: AllSampler
+ # Skip some traces if the root span tag values matches some regexp patterns
+ # skipTagsPatterns: {"http.url": ".*/demo/add.*"}
-# Enable custom tracing (annotations)
+# Enable custom tracing (Custom annotations for now)
# enableCustomTracing: true
+
+# Disable some instrumentations
+# disabledInstrumentations: ["apache http", "mongo", "jetty", "tomcat", ...]
\ No newline at end of file

MODIFY
dd-java-agent/src/test/java/io/opentracing/contrib/agent/TraceAnnotationsManagerTest.java
dd-java-agent/src/test/java/io/opentracing/contrib/agent/TraceAnnotationsManagerTest.java
@@ -15,11 +15,11 @@ public class TraceAnnotationsManagerTest {
@Before
public void beforeTest() throws Exception {
GlobalTracer.register(tracer);
- TraceAnnotationsManager.loadRules(ClassLoader.getSystemClassLoader());
+ TraceAnnotationsManager.loadAnnotationsRules(ClassLoader.getSystemClassLoader());
}
@Test
- public void test() {
+ public void testAnnotations() {
//Test single span in new trace
SayTracedHello.sayHello();

MODIFY
dd-trace-examples/dropwizard-mongo-client/src/main/resources/dd-trace.yaml
dd-trace-examples/dropwizard-mongo-client/src/main/resources/dd-trace.yaml
@@ -22,5 +22,8 @@ sampler:
# Skip some traces if the root span tag values matches some regexp patterns
# skipTagsPatterns: {"http.url": ".*/demo/add.*"}
-# Enable custom tracing (annotations)
+# Enable custom tracing (Custom annotations for now)
enableCustomTracing: true
+
+# Disable some instrumentations
+# disabledInstrumentations: ["apache http", "mongo", "jetty", "tomcat", ...]
\ No newline at end of file

New feature: disabling instrumentations