+ * This will always return a {@link IAuthProvider}.
+ *
+ * @param settings the current settings
+ * @param reflection the reflection service that is available
+ * @return the loaded {@link IAuthProvider}
+ */
+ public static IAuthProvider provider(final ISettings settings, final IReflection reflection) {
final String serviceAuthProvider = settings.getSettingAs("service.auth.provider", String.class);
if (serviceAuthProvider == null || serviceAuthProvider.trim().isEmpty()) {
return NOOP_PROVIDER;
@@ -48,19 +64,14 @@ public static IAuthProvider provider(final ISettings settings) {
try {
final Class> aClass = Class.forName(serviceAuthProvider);
- final Constructor> constructor = aClass.getConstructor(ISettings.class);
- final Object newInstance = constructor.newInstance(settings);
- return (IAuthProvider) newInstance;
- } catch (ClassNotFoundException
- | NoSuchMethodException
- | InvocationTargetException
- | InstantiationException
- | IllegalAccessException e) {
+ final Constructor> constructor = ReflectionUtils.findConstructor(aClass, reflection);
+ return ReflectionUtils.callConstructor(constructor, settings, reflection);
+ } catch (ClassNotFoundException e) {
throw new RuntimeException(String.format("Cannot load auth provider %s", serviceAuthProvider), e);
}
}
- private static class NoopProvider implements IAuthProvider {
+ static class NoopProvider implements IAuthProvider {
@Override
public Map
+ * This provider can be set using {@code service.auth.provider=com.intergral.deep.agent.api.auth.BasicAuthProvider}. The username and
+ * password that is configured onto requests can be set with the setting:
+ *
+ * These values are then base64 encoded and attached to the outbound requests as the {@code authorization} header.
+ */
public class BasicAuthProvider implements IAuthProvider {
private final ISettings settings;
diff --git a/agent-api/src/main/java/com/intergral/deep/agent/api/auth/IAuthProvider.java b/agent-api/src/main/java/com/intergral/deep/agent/api/auth/IAuthProvider.java
index dda8c64..dbbfcd9 100644
--- a/agent-api/src/main/java/com/intergral/deep/agent/api/auth/IAuthProvider.java
+++ b/agent-api/src/main/java/com/intergral/deep/agent/api/auth/IAuthProvider.java
@@ -19,10 +19,14 @@
import java.util.Map;
+/**
+ * Allows for custom auth providers to be configured. These can be provided as an instantiatable class using the class name via the setting
+ * {@code service.auth.provider}. Alternatively a plugin can be configured as an auth provider.
+ */
public interface IAuthProvider {
/**
- * Provide the headers that should be attached to the GRPC calls
+ * Provide the headers that should be attached to the GRPC calls.
*
* @return a Map of the header values
*/
diff --git a/agent-api/src/main/java/com/intergral/deep/agent/api/hook/IDeepHook.java b/agent-api/src/main/java/com/intergral/deep/agent/api/hook/IDeepHook.java
index 291f146..72d7044 100644
--- a/agent-api/src/main/java/com/intergral/deep/agent/api/hook/IDeepHook.java
+++ b/agent-api/src/main/java/com/intergral/deep/agent/api/hook/IDeepHook.java
@@ -20,9 +20,22 @@
import com.intergral.deep.agent.api.IDeep;
import com.intergral.deep.agent.api.reflection.IReflection;
+/**
+ * This type is used to pass an object from the agent to the API. It should not be directly used by clients.
+ */
public interface IDeepHook {
+ /**
+ * Get the deep service from the agent.
+ *
+ * @return the deep agent.
+ */
IDeep deepService();
+ /**
+ * Get the configured reflection api.
+ *
+ * @return the reflection api.
+ */
IReflection reflectionService();
}
diff --git a/agent-api/src/main/java/com/intergral/deep/agent/api/plugin/AbstractEvaluator.java b/agent-api/src/main/java/com/intergral/deep/agent/api/plugin/AbstractEvaluator.java
index f5b5030..80bc961 100644
--- a/agent-api/src/main/java/com/intergral/deep/agent/api/plugin/AbstractEvaluator.java
+++ b/agent-api/src/main/java/com/intergral/deep/agent/api/plugin/AbstractEvaluator.java
@@ -34,6 +34,22 @@ public boolean evaluate(final String expression, final Map
+ * As Java doesn't have inherit truthiness such as JavaScript. We want to simulate it here, we will convert the following to inputs, all
+ * other inputs are {@code true}.
+ *
* By default, this will check the Deep settings for the plugin name. e.g. the setting com.intergral.deep.plugin.JavaPlugin.active=false
- * will disable the JavaPlugin. The normal settings rules apply, e.g. deep. or DEEP_ as a prefix when using system properties or environment variables.
+ * will disable the JavaPlugin. The normal settings rules apply, e.g. deep. or DEEP_ as a prefix when using system properties
+ * or environment variables.
*
* @param settings the current deep settings.
* @return {@code false} if setting is 'false', otherwise {@code true}
@@ -73,10 +74,10 @@ default boolean isActive(final ISettings settings) {
interface IPluginRegistration extends IRegistration
+ * This will look for the method using {@link #findMethod(Class, String, Class[])} using the input arguments as the argument types of the
+ * method. The method will then be invoked on the target argument.
+ *
+ * @param target the target instance to call the method on
+ * @param methodName the name of the method to call
+ * @param args the arguments to the method
+ * @param
+ * Will look for the constructor that we can use in the order:
+ *
+ * By default, tomcat take index.jsp and make it into index_jsp.class, but this suffix can be configured.
+ */
+ String JSP_SUFFIX = "jsp.suffix";
+ /**
+ * It is possible to put compiled JSP classes into specified packages, some versions put this in a {@code jsp} package, some use
+ * {@code org.apache.jsp} (newer).
+ */
+ String JSP_PACKAGES = "jsp.packages";
+
+ /**
+ * Define which packages we should include as being part of your app.
+ */
+ String APP_FRAMES_INCLUDES = "in.app.include";
+
+ /**
+ * Define which packages we should exclude as being part of your app.
+ */
+ String APP_FRAMES_EXCLUDES = "in.app.include";
+
+ /**
+ * Get a setting from the config as a given type.
+ *
+ * @param key the key for the setting
+ * @param clazz the type to return as
+ * @param
+ *
+ *
+ *
+ *
+ * @param obj the value to convert
+ * @return the value as a boolean
+ * @see Boolean#parseBoolean(String)
+ */
public static boolean objectToBoolean(final Object obj) {
if (obj == null) {
return false;
diff --git a/agent-api/src/main/java/com/intergral/deep/agent/api/plugin/EvaluationException.java b/agent-api/src/main/java/com/intergral/deep/agent/api/plugin/EvaluationException.java
index ccb22b1..7058b90 100644
--- a/agent-api/src/main/java/com/intergral/deep/agent/api/plugin/EvaluationException.java
+++ b/agent-api/src/main/java/com/intergral/deep/agent/api/plugin/EvaluationException.java
@@ -28,7 +28,7 @@ public class EvaluationException extends Exception {
private final String expression;
/**
- * Create a new exception
+ * Create a new exception.
*
* @param expression the expression that failed
* @param cause the failure
@@ -39,7 +39,7 @@ public EvaluationException(final String expression, final Throwable cause) {
}
/**
- * Get the expression
+ * Get the expression.
*
* @return {@link #expression}
*/
diff --git a/agent-api/src/main/java/com/intergral/deep/agent/api/plugin/IEvaluator.java b/agent-api/src/main/java/com/intergral/deep/agent/api/plugin/IEvaluator.java
index 919a1c0..a74ffec 100644
--- a/agent-api/src/main/java/com/intergral/deep/agent/api/plugin/IEvaluator.java
+++ b/agent-api/src/main/java/com/intergral/deep/agent/api/plugin/IEvaluator.java
@@ -19,10 +19,30 @@
import java.util.Map;
+/**
+ * This defines an evaluator, and evaluator is used to evaluate expression at runtime. ie allows a watch or condition to execute within the
+ * scope of the tracepoint.
+ */
public interface IEvaluator {
+ /**
+ * Evaluate an expression as a boolean response.
+ *
+ * @param expression the expression to evaluate
+ * @param values the variables that the expression can evaluate against
+ * @return {@code true} if the expression evaluates to truthy value.
+ * @see AbstractEvaluator#objectToBoolean(Object)
+ */
boolean evaluate(final String expression, final Map
+ *
+ *
+ * @param clazz the class to look on
+ * @param reflection the reflection service to use
+ * @return the constructor that was found
+ * @throws DeepRuntimeException if we could not find a constructor
+ */
+ public static Constructor> findConstructor(final Class> clazz, final IReflection reflection) {
+
+ final Constructor> constructor = reflection.findConstructor(clazz, ISettings.class);
+ if (constructor != null) {
+ return constructor;
+ }
+
+ final Constructor> defaultConstructor = reflection.findConstructor(clazz);
+ if (defaultConstructor != null) {
+ return defaultConstructor;
+ }
+ final String simpleName = clazz.getSimpleName();
+ throw new DeepRuntimeException(
+ String.format("Cannot create auth provider of type: %s. Class is missing constructor %s(%s) or %s().", clazz.getName(),
+ simpleName, ISettings.class.getName(), simpleName));
+
+ }
+
+}
diff --git a/agent-api/src/main/java/com/intergral/deep/agent/api/resource/ConfigurationException.java b/agent-api/src/main/java/com/intergral/deep/agent/api/resource/ConfigurationException.java
deleted file mode 100644
index c560a81..0000000
--- a/agent-api/src/main/java/com/intergral/deep/agent/api/resource/ConfigurationException.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package com.intergral.deep.agent.api.resource;
-
-/**
- * An exception that is thrown if the user-provided configuration is invalid.
- */
-public final class ConfigurationException extends RuntimeException {
-
- /**
- * Create a new configuration exception with specified {@code message} and without a cause.
- *
- * @param message The exception message
- */
- public ConfigurationException(String message) {
- super(message);
- }
-
- /**
- * Create a new configuration exception with specified {@code message} and {@code cause}.
- *
- * @param message The exception message
- * @param cause The root cause of this exception
- */
- public ConfigurationException(String message, Throwable cause) {
- super(message, cause);
- }
-}
diff --git a/agent-api/src/main/java/com/intergral/deep/agent/api/resource/ResourceAttributes.java b/agent-api/src/main/java/com/intergral/deep/agent/api/resource/ResourceAttributes.java
index 98872d9..bdcbe5c 100644
--- a/agent-api/src/main/java/com/intergral/deep/agent/api/resource/ResourceAttributes.java
+++ b/agent-api/src/main/java/com/intergral/deep/agent/api/resource/ResourceAttributes.java
@@ -1,22 +1,14 @@
/*
- * Copyright 2023 Intergral GmbH
- *
- * 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.
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
*/
package com.intergral.deep.agent.api.resource;
-public class ResourceAttributes {
+/**
+ * A collection of known keys that are used in the attributes.
+ */
+public interface ResourceAttributes {
/**
* Logical name of the service.
@@ -31,20 +23,20 @@ public class ResourceAttributes {
* MUST be set to {@code unknown_service}.
*
*/
- public static final String SERVICE_NAME = "service.name";
+ String SERVICE_NAME = "service.name";
/**
* The name of the telemetry SDK as defined above.
*/
- public static final String TELEMETRY_SDK_NAME = "telemetry.sdk.name";
+ String TELEMETRY_SDK_NAME = "telemetry.sdk.name";
/**
* The language of the telemetry SDK.
*/
- public static final String TELEMETRY_SDK_LANGUAGE = "telemetry.sdk.language";
+ String TELEMETRY_SDK_LANGUAGE = "telemetry.sdk.language";
/**
* The version string of the telemetry SDK.
*/
- public static final String TELEMETRY_SDK_VERSION = "telemetry.sdk.version";
+ String TELEMETRY_SDK_VERSION = "telemetry.sdk.version";
}
diff --git a/agent-api/src/main/java/com/intergral/deep/agent/api/settings/ISettings.java b/agent-api/src/main/java/com/intergral/deep/agent/api/settings/ISettings.java
index 8fa00c0..75e2e4f 100644
--- a/agent-api/src/main/java/com/intergral/deep/agent/api/settings/ISettings.java
+++ b/agent-api/src/main/java/com/intergral/deep/agent/api/settings/ISettings.java
@@ -21,10 +21,13 @@
import com.intergral.deep.agent.api.resource.Resource;
import java.util.Map;
+/**
+ * The exposed API for the Deep settings.
+ */
public interface ISettings {
/**
- * This is the settings key for the configured auth provider
+ * This is the settings key for the configured auth provider.
*/
String KEY_AUTH_PROVIDER = "service.auth.provider";
@@ -34,16 +37,62 @@ public interface ISettings {
String KEY_ENABLED = "enabled";
/**
- * This is the setting key for the service url
+ * This is the setting key for the service url.
*/
String KEY_SERVICE_URL = "service.url";
+ /**
+ * This is the setting key for the service secure setting.
+ */
+ String KEY_SERVICE_SECURE = "service.secure";
+
+ /**
+ * This is the setting key for the plugin list.
+ */
+ String PLUGINS = "plugins";
+
+ /**
+ * To let us calculate the class and file names for JSP classes we need to know the JSP suffix that is being used by monitored service.
+ *