diff options
author | Stefan Schmidt <ubschmidt2@users.noreply.github.com> | 2017-11-20 20:59:30 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-11-20 20:59:30 +0100 |
commit | cdd4ce23766816ea4f8df66b035d961b652b5d00 (patch) | |
tree | a976272210cef6d0d109d9d9ea0c226a80d27f1f /contrib | |
parent | 6484142b2392fd549f47603156c5a9f3dd9376ba (diff) | |
download | opencensus-java-cdd4ce23766816ea4f8df66b035d961b652b5d00.tar.gz |
Add initial support for configuring the agent. (#753)
* Add initial support for configuring the agent.
* Add a simple unit test to check the effect of the config knob.
* No need for static here.
* Use non-deprecated MockitoJUnitRunner.
* Add another naive unit test.
* ./gradlew googleJavaFormat
* Add another naive unit test.
* Suffix feature-paths with .enabled to allow for feature-specific detail config.
* Update example to use the new config path.
* Revert Mockito upgrade.
Diffstat (limited to 'contrib')
13 files changed, 258 insertions, 9 deletions
diff --git a/contrib/agent/README.md b/contrib/agent/README.md index 80a3ce21..b0ae3803 100644 --- a/contrib/agent/README.md +++ b/contrib/agent/README.md @@ -65,6 +65,26 @@ executable as shown in the following example. Replace `X.Y.Z` with the actual ve java -javaagent:path/to/opencensus-contrib-agent-X.Y.Z.jar ... ``` + +## Configuration + +The *OpenCensus Agent for Java* uses [Typesafe's configuration +library](https://lightbend.github.io/config/) for all user-configurable settings. Please refer to +[reference.conf](src/main/resources/reference.conf) for the available configuration knobs and their +defaults. + +You can override the default configuration in [different +ways](https://github.com/lightbend/config/blob/7cae92d3ae3ff9d06f1db43800232d2f73c6fe44/README.md#standard-behavior). +For example, to disable the automatic context propagation for Executors, add a system property as +follows: + +```shell +java -javaagent:path/to/opencensus-contrib-agent-X.Y.Z.jar \ + -Dopencensus.contrib.agent.context-propagation.executor.enabled=false \ + ... +``` + + [travis-image]: https://travis-ci.org/census-instrumentation/opencensus-java.svg?branch=master [travis-url]: https://travis-ci.org/census-instrumentation/opencensus-java [appveyor-image]: https://ci.appveyor.com/api/projects/status/hxthmpkxar4jq4be/branch/master?svg=true diff --git a/contrib/agent/build.gradle b/contrib/agent/build.gradle index a03445d7..6177e0f3 100644 --- a/contrib/agent/build.gradle +++ b/contrib/agent/build.gradle @@ -24,9 +24,10 @@ dependencies { compileOnly libraries.auto_service compileOnly libraries.grpc_context compileOnly project(':opencensus-api') + compile libraries.byte_buddy + compile libraries.config compile libraries.findbugs_annotations compile libraries.guava - compile libraries.byte_buddy signature 'org.codehaus.mojo.signature:java16:+@signature' } @@ -61,6 +62,7 @@ shadowJar { // Include only the following dependencies (excluding transitive dependencies). dependencies { include(dependency(libraries.byte_buddy)) + include(dependency(libraries.config)) include(dependency(libraries.guava)) } @@ -72,6 +74,8 @@ shadowJar { // classes, which are loaded by the same classloader (the system classloader). // Byte Buddy: relocate 'net.bytebuddy', agentRepackaged + '.bytebuddy' + // Config: + relocate 'com.typesafe.config', agentRepackaged + '.config' // Guava: relocate 'com.google.common', agentRepackaged + '.guava' relocate 'com.google.thirdparty.publicsuffix', agentRepackaged + '.publicsuffix' @@ -99,7 +103,8 @@ shadowJar { // ... except for the expected entries. [ agentPackageDir, 'META-INF/MANIFEST.MF', - 'META-INF/services/io.opencensus.contrib.agent.instrumentation.Instrumenter' + 'META-INF/services/io.opencensus.contrib.agent.instrumentation.Instrumenter', + 'reference.conf', ].any { entry.isDirectory() ? it.startsWith(entry.name) : it == entry.name } // Also, should not have the bootstrap classes. assert !entry.name.startsWith(agentBootstrapPackageDir) diff --git a/contrib/agent/src/main/java/io/opencensus/contrib/agent/AgentMain.java b/contrib/agent/src/main/java/io/opencensus/contrib/agent/AgentMain.java index 020987b4..f0866c30 100644 --- a/contrib/agent/src/main/java/io/opencensus/contrib/agent/AgentMain.java +++ b/contrib/agent/src/main/java/io/opencensus/contrib/agent/AgentMain.java @@ -20,6 +20,8 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; import static net.bytebuddy.matcher.ElementMatchers.none; +import com.typesafe.config.Config; +import com.typesafe.config.ConfigFactory; import io.opencensus.contrib.agent.bootstrap.ContextStrategy; import io.opencensus.contrib.agent.bootstrap.ContextTrampoline; import io.opencensus.contrib.agent.instrumentation.Instrumenter; @@ -73,6 +75,7 @@ public final class AgentMain { checkLoadedByBootstrapClassloader(ContextTrampoline.class); checkLoadedByBootstrapClassloader(ContextStrategy.class); + Config config = readConfig(); AgentBuilder agentBuilder = new AgentBuilder.Default() .disableClassFormatChanges() @@ -80,7 +83,7 @@ public final class AgentMain { .with(new AgentBuilderListener()) .ignore(none()); for (Instrumenter instrumenter : ServiceLoader.load(Instrumenter.class)) { - agentBuilder = instrumenter.instrument(agentBuilder); + agentBuilder = instrumenter.instrument(agentBuilder, config); } agentBuilder.installOn(instrumentation); @@ -91,4 +94,12 @@ public final class AgentMain { checkState( clazz.getClassLoader() == null, "%s must be loaded by the bootstrap classloader", clazz); } + + private static Config readConfig() { + final String configPath = "opencensus.contrib.agent"; + Config config = ConfigFactory.load(); + config.checkValid(ConfigFactory.defaultReference(), configPath); + + return config.getConfig(configPath); + } } diff --git a/contrib/agent/src/main/java/io/opencensus/contrib/agent/instrumentation/ContextTrampolineInitializer.java b/contrib/agent/src/main/java/io/opencensus/contrib/agent/instrumentation/ContextTrampolineInitializer.java index 1ed18857..64357cce 100644 --- a/contrib/agent/src/main/java/io/opencensus/contrib/agent/instrumentation/ContextTrampolineInitializer.java +++ b/contrib/agent/src/main/java/io/opencensus/contrib/agent/instrumentation/ContextTrampolineInitializer.java @@ -17,6 +17,7 @@ package io.opencensus.contrib.agent.instrumentation; import com.google.auto.service.AutoService; +import com.typesafe.config.Config; import io.opencensus.contrib.agent.bootstrap.ContextStrategy; import io.opencensus.contrib.agent.bootstrap.ContextTrampoline; import net.bytebuddy.agent.builder.AgentBuilder; @@ -26,7 +27,7 @@ import net.bytebuddy.agent.builder.AgentBuilder; public final class ContextTrampolineInitializer implements Instrumenter { @Override - public AgentBuilder instrument(AgentBuilder agentBuilder) { + public AgentBuilder instrument(AgentBuilder agentBuilder, Config config) { // TODO(stschmidt): Gracefully handle the case of missing io.grpc.Context at runtime, // maybe load the missing classes from a JAR that comes with the agent JAR. ContextTrampoline.setContextStrategy(new ContextStrategyImpl()); diff --git a/contrib/agent/src/main/java/io/opencensus/contrib/agent/instrumentation/ExecutorInstrumentation.java b/contrib/agent/src/main/java/io/opencensus/contrib/agent/instrumentation/ExecutorInstrumentation.java index 669c0627..915ed2c6 100644 --- a/contrib/agent/src/main/java/io/opencensus/contrib/agent/instrumentation/ExecutorInstrumentation.java +++ b/contrib/agent/src/main/java/io/opencensus/contrib/agent/instrumentation/ExecutorInstrumentation.java @@ -25,6 +25,7 @@ import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.not; import com.google.auto.service.AutoService; +import com.typesafe.config.Config; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import io.opencensus.contrib.agent.bootstrap.ContextTrampoline; import java.util.concurrent.Executor; @@ -44,8 +45,13 @@ import net.bytebuddy.utility.JavaModule; public final class ExecutorInstrumentation implements Instrumenter { @Override - public AgentBuilder instrument(AgentBuilder agentBuilder) { + public AgentBuilder instrument(AgentBuilder agentBuilder, Config config) { checkNotNull(agentBuilder, "agentBuilder"); + checkNotNull(config, "config"); + + if (!config.getBoolean("context-propagation.executor.enabled")) { + return agentBuilder; + } return agentBuilder.type(createMatcher()).transform(new Transformer()); } diff --git a/contrib/agent/src/main/java/io/opencensus/contrib/agent/instrumentation/Instrumenter.java b/contrib/agent/src/main/java/io/opencensus/contrib/agent/instrumentation/Instrumenter.java index 9168eef6..37ca1507 100644 --- a/contrib/agent/src/main/java/io/opencensus/contrib/agent/instrumentation/Instrumenter.java +++ b/contrib/agent/src/main/java/io/opencensus/contrib/agent/instrumentation/Instrumenter.java @@ -16,6 +16,7 @@ package io.opencensus.contrib.agent.instrumentation; +import com.typesafe.config.Config; import net.bytebuddy.agent.builder.AgentBuilder; /** Interface for plug-ins that add bytecode instrumentation. */ @@ -26,7 +27,8 @@ public interface Instrumenter { * * @param agentBuilder an {@link AgentBuilder} object to which the additional instrumentation is * added + * @param config the configuration settings * @return an {@link AgentBuilder} object having the additional instrumentation */ - AgentBuilder instrument(AgentBuilder agentBuilder); + AgentBuilder instrument(AgentBuilder agentBuilder, Config config); } diff --git a/contrib/agent/src/main/java/io/opencensus/contrib/agent/instrumentation/ThreadInstrumentation.java b/contrib/agent/src/main/java/io/opencensus/contrib/agent/instrumentation/ThreadInstrumentation.java index a1b6e17e..76be89fc 100644 --- a/contrib/agent/src/main/java/io/opencensus/contrib/agent/instrumentation/ThreadInstrumentation.java +++ b/contrib/agent/src/main/java/io/opencensus/contrib/agent/instrumentation/ThreadInstrumentation.java @@ -21,6 +21,7 @@ import static net.bytebuddy.matcher.ElementMatchers.isSubTypeOf; import static net.bytebuddy.matcher.ElementMatchers.named; import com.google.auto.service.AutoService; +import com.typesafe.config.Config; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import io.opencensus.contrib.agent.bootstrap.ContextTrampoline; import net.bytebuddy.agent.builder.AgentBuilder; @@ -42,8 +43,13 @@ import net.bytebuddy.utility.JavaModule; public final class ThreadInstrumentation implements Instrumenter { @Override - public AgentBuilder instrument(AgentBuilder agentBuilder) { + public AgentBuilder instrument(AgentBuilder agentBuilder, Config config) { checkNotNull(agentBuilder, "agentBuilder"); + checkNotNull(config, "config"); + + if (!config.getBoolean("context-propagation.thread.enabled")) { + return agentBuilder; + } return agentBuilder.type(isSubTypeOf(Thread.class)).transform(new Transformer()); } diff --git a/contrib/agent/src/main/java/io/opencensus/contrib/agent/instrumentation/TraceTrampolineInitializer.java b/contrib/agent/src/main/java/io/opencensus/contrib/agent/instrumentation/TraceTrampolineInitializer.java index 4d879458..e755ab45 100644 --- a/contrib/agent/src/main/java/io/opencensus/contrib/agent/instrumentation/TraceTrampolineInitializer.java +++ b/contrib/agent/src/main/java/io/opencensus/contrib/agent/instrumentation/TraceTrampolineInitializer.java @@ -17,6 +17,7 @@ package io.opencensus.contrib.agent.instrumentation; import com.google.auto.service.AutoService; +import com.typesafe.config.Config; import io.opencensus.contrib.agent.bootstrap.TraceStrategy; import io.opencensus.contrib.agent.bootstrap.TraceTrampoline; import net.bytebuddy.agent.builder.AgentBuilder; @@ -26,7 +27,7 @@ import net.bytebuddy.agent.builder.AgentBuilder; public final class TraceTrampolineInitializer implements Instrumenter { @Override - public AgentBuilder instrument(AgentBuilder agentBuilder) { + public AgentBuilder instrument(AgentBuilder agentBuilder, Config config) { // TODO(stschmidt): Gracefully handle the case of missing trace API at runtime, // maybe load the missing classes from a JAR that comes with the agent JAR. TraceTrampoline.setTraceStrategy(new TraceStrategyImpl()); diff --git a/contrib/agent/src/main/java/io/opencensus/contrib/agent/instrumentation/UrlInstrumentation.java b/contrib/agent/src/main/java/io/opencensus/contrib/agent/instrumentation/UrlInstrumentation.java index 40bc2f79..18326ca7 100644 --- a/contrib/agent/src/main/java/io/opencensus/contrib/agent/instrumentation/UrlInstrumentation.java +++ b/contrib/agent/src/main/java/io/opencensus/contrib/agent/instrumentation/UrlInstrumentation.java @@ -21,6 +21,7 @@ import static net.bytebuddy.matcher.ElementMatchers.named; import com.google.auto.service.AutoService; import com.google.errorprone.annotations.MustBeClosed; +import com.typesafe.config.Config; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import io.opencensus.contrib.agent.bootstrap.TraceTrampoline; import java.io.Closeable; @@ -40,8 +41,13 @@ import net.bytebuddy.utility.JavaModule; public final class UrlInstrumentation implements Instrumenter { @Override - public AgentBuilder instrument(AgentBuilder agentBuilder) { + public AgentBuilder instrument(AgentBuilder agentBuilder, Config config) { checkNotNull(agentBuilder, "agentBuilder"); + checkNotNull(config, "config"); + + if (!config.getBoolean("trace.java.net.URL.getContent.enabled")) { + return agentBuilder; + } return agentBuilder.type(named("java.net.URL")).transform(new Transformer()); } diff --git a/contrib/agent/src/main/resources/reference.conf b/contrib/agent/src/main/resources/reference.conf new file mode 100644 index 00000000..e1781248 --- /dev/null +++ b/contrib/agent/src/main/resources/reference.conf @@ -0,0 +1,23 @@ +# Reference configuration for the OpenCensus Agent for Java. + +opencensus.contrib.agent { + + # Configuration settings related to automatic context propagation. + context-propagation { + + # Enable/disable automatic context propagation for Executors. + executor.enabled = true + + # Enable/disable automatic context propagation for Threads. + thread.enabled = true + } + + # The "trace" section configures which Java methods the agent instruments for + # tracing. + trace { + + java.net.URL.getContent { + enabled = true + } + } +} diff --git a/contrib/agent/src/test/java/io/opencensus/contrib/agent/instrumentation/ExecutorInstrumentationTest.java b/contrib/agent/src/test/java/io/opencensus/contrib/agent/instrumentation/ExecutorInstrumentationTest.java new file mode 100644 index 00000000..51c7c5ae --- /dev/null +++ b/contrib/agent/src/test/java/io/opencensus/contrib/agent/instrumentation/ExecutorInstrumentationTest.java @@ -0,0 +1,56 @@ +/* + * Copyright 2017, OpenCensus Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.opencensus.contrib.agent.instrumentation; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.when; + +import com.typesafe.config.Config; +import net.bytebuddy.agent.builder.AgentBuilder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +/** Unit tests for {@link ExecutorInstrumentation}. */ +@RunWith(MockitoJUnitRunner.class) +public class ExecutorInstrumentationTest { + + @Mock private Config config; + + private final ExecutorInstrumentation instrumentation = new ExecutorInstrumentation(); + + private final AgentBuilder agentBuilder = new AgentBuilder.Default(); + + @Test + public void instrument_disabled() { + when(config.getBoolean("context-propagation.executor.enabled")).thenReturn(false); + + AgentBuilder agentBuilder2 = instrumentation.instrument(agentBuilder, config); + + assertThat(agentBuilder2).isSameAs(agentBuilder); + } + + @Test + public void instrument_enabled() { + when(config.getBoolean("context-propagation.executor.enabled")).thenReturn(true); + + AgentBuilder agentBuilder2 = instrumentation.instrument(agentBuilder, config); + + assertThat(agentBuilder2).isNotSameAs(agentBuilder); + } +} diff --git a/contrib/agent/src/test/java/io/opencensus/contrib/agent/instrumentation/ThreadInstrumentationTest.java b/contrib/agent/src/test/java/io/opencensus/contrib/agent/instrumentation/ThreadInstrumentationTest.java new file mode 100644 index 00000000..1df44fe0 --- /dev/null +++ b/contrib/agent/src/test/java/io/opencensus/contrib/agent/instrumentation/ThreadInstrumentationTest.java @@ -0,0 +1,56 @@ +/* + * Copyright 2017, OpenCensus Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.opencensus.contrib.agent.instrumentation; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.when; + +import com.typesafe.config.Config; +import net.bytebuddy.agent.builder.AgentBuilder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +/** Unit tests for {@link ThreadInstrumentation}. */ +@RunWith(MockitoJUnitRunner.class) +public class ThreadInstrumentationTest { + + @Mock private Config config; + + private final ThreadInstrumentation instrumentation = new ThreadInstrumentation(); + + private final AgentBuilder agentBuilder = new AgentBuilder.Default(); + + @Test + public void instrument_disabled() { + when(config.getBoolean("context-propagation.thread.enabled")).thenReturn(false); + + AgentBuilder agentBuilder2 = instrumentation.instrument(agentBuilder, config); + + assertThat(agentBuilder2).isSameAs(agentBuilder); + } + + @Test + public void instrument_enabled() { + when(config.getBoolean("context-propagation.thread.enabled")).thenReturn(true); + + AgentBuilder agentBuilder2 = instrumentation.instrument(agentBuilder, config); + + assertThat(agentBuilder2).isNotSameAs(agentBuilder); + } +} diff --git a/contrib/agent/src/test/java/io/opencensus/contrib/agent/instrumentation/UrlInstrumentationTest.java b/contrib/agent/src/test/java/io/opencensus/contrib/agent/instrumentation/UrlInstrumentationTest.java new file mode 100644 index 00000000..29ddadc7 --- /dev/null +++ b/contrib/agent/src/test/java/io/opencensus/contrib/agent/instrumentation/UrlInstrumentationTest.java @@ -0,0 +1,56 @@ +/* + * Copyright 2017, OpenCensus Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.opencensus.contrib.agent.instrumentation; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.when; + +import com.typesafe.config.Config; +import net.bytebuddy.agent.builder.AgentBuilder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +/** Unit tests for {@link UrlInstrumentation}. */ +@RunWith(MockitoJUnitRunner.class) +public class UrlInstrumentationTest { + + @Mock private Config config; + + private final UrlInstrumentation instrumentation = new UrlInstrumentation(); + + private final AgentBuilder agentBuilder = new AgentBuilder.Default(); + + @Test + public void instrument_disabled() { + when(config.getBoolean("trace.java.net.URL.getContent.enabled")).thenReturn(false); + + AgentBuilder agentBuilder2 = instrumentation.instrument(agentBuilder, config); + + assertThat(agentBuilder2).isSameAs(agentBuilder); + } + + @Test + public void instrument_enabled() { + when(config.getBoolean("trace.java.net.URL.getContent.enabled")).thenReturn(true); + + AgentBuilder agentBuilder2 = instrumentation.instrument(agentBuilder, config); + + assertThat(agentBuilder2).isNotSameAs(agentBuilder); + } +} |