Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .idea/encodings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright (C) 2023 Intergral GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package com.intergral.deep.agent.api.plugin;

/**
* This type can be used to connect Deep to a trace provider. This will allow Deep to create Spans dynamically based on the config of a
* tracepoint.
*/
public interface ITraceProvider {

/**
* Create and return a new span.
*
* @param name the name of the span to create
* @return the new span
*/
ISpan createSpan(final String name);

/**
* Get the current span from the underlying provider.
*
* @return the current active span, or {@code null}
*/
ISpan currentSpan();

/**
* This type describes a span for Deep to use as a dynamic Span, it gives a common interface for all {@link ITraceProvider}'s.
*/
interface ISpan extends AutoCloseable {
String name();

String traceId();

String spanId();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package com.intergral.deep.agent.api.spi;

import com.intergral.deep.agent.api.plugin.ITraceProvider;
import com.intergral.deep.agent.api.reflection.IReflection;
import com.intergral.deep.agent.api.settings.ISettings;

Expand All @@ -30,6 +31,7 @@
* allow plugins to provide additional attributes to captured snapshots</li>
* <li>{@link com.intergral.deep.agent.api.auth.IAuthProvider} - allow plugin to provide additional ways to authenticate</li>
* <li>{@link ResourceProvider} - allow plugins to provide additional information for the resource definition</li>
* <li>{@link ITraceProvider} - allows plugins to connect deep to a tracing provider</li>
* </ul>
* <p>
* Plugins will be instantiated via the default constructor and then the {@link #configure(ISettings, IReflection)}
Expand Down
6 changes: 6 additions & 0 deletions agent/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.intergral.deep.plugins</groupId>
<artifactId>otel-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>


<!-- we use slf4j api but JUL impl for logging -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,21 @@ public IDeepPlugin get() {
};
}

/**
* Get the first plugin that matches the given type.
*
* @param clazz the type of plugin we need
* @param <T> the plugin type
* @return the discovered plugin or {@code null} if we couldn't find a plugin of this type.
*/
public <T> T getPlugin(final Class<T> clazz) {
final Collection<T> plugins = this.getPlugins(clazz);
if (plugins.isEmpty()) {
return null;
}
return plugins.iterator().next();
}

/**
* Used to indicate an invalid config value.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,18 @@

import com.intergral.deep.agent.Utils;
import com.intergral.deep.agent.api.plugin.IEvaluator;
import com.intergral.deep.agent.api.plugin.ITraceProvider;
import com.intergral.deep.agent.api.plugin.ITraceProvider.ISpan;
import com.intergral.deep.agent.api.plugin.LazyEvaluator;
import com.intergral.deep.agent.push.PushService;
import com.intergral.deep.agent.settings.Settings;
import com.intergral.deep.agent.tracepoint.TracepointConfigService;
import com.intergral.deep.agent.tracepoint.cf.CFEvaluator;
import com.intergral.deep.agent.tracepoint.cf.CFFrameProcessor;
import com.intergral.deep.agent.tracepoint.evaluator.EvaluatorService;
import com.intergral.deep.agent.tracepoint.inst.asm.Visitor;
import com.intergral.deep.agent.types.TracePointConfig;
import com.intergral.deep.agent.types.snapshot.EventSnapshot;
import java.io.Closeable;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
Expand Down Expand Up @@ -66,7 +68,7 @@ protected Boolean initialValue() {

private static TracepointConfigService TRACEPOINT_SERVICE;
private static PushService PUSH_SERVICE;
private static int offset;
private static int OFFSET;

/**
* Initialise the callback with the deep services.
Expand All @@ -82,10 +84,12 @@ public static void init(
Callback.SETTINGS = settings;
Callback.TRACEPOINT_SERVICE = tracepointConfigService;
Callback.PUSH_SERVICE = pushService;
if (Visitor.CALLBACK_CLASS == Callback.class) {
offset = 3;
// to avoid using the property Visitor.CALLBACK_CLASS (as this defaults to a java. class that makes tests complicated)
final String property = System.getProperty("deep.callback.class");
if (property == null || !property.equals(Callback.class.getName())) {
Callback.OFFSET = 4;
} else {
offset = 4;
Callback.OFFSET = 3;
}
}

Expand Down Expand Up @@ -156,9 +160,9 @@ private static void commonCallback(final List<String> tracepointIds,
tracepointIds);

StackTraceElement[] stack = Thread.currentThread().getStackTrace();
if (stack.length > offset) {
if (stack.length > OFFSET) {
// Remove callBackProxy() + callBack() + commonCallback() + getStackTrace() entries to get to the real bp location
stack = Arrays.copyOfRange(stack, offset, stack.length);
stack = Arrays.copyOfRange(stack, OFFSET, stack.length);
}

final FrameProcessor frameProcessor = factory.provide(Callback.SETTINGS,
Expand Down Expand Up @@ -314,4 +318,42 @@ public static void callBackFinally(final Set<String> breakpointIds,
// return String.format( "%s:%s", value.getRelPath(), value.getLineNo() );
// }
// }

/**
* Create a span using the tracepoint callback.
* <p>
* This method will <b>Always</b> return a closable. This way the injected code never deals with anything but calling close. Even if close
* doesn't do anything.
* <p>
* We use {@link Closeable} here, so we can stick to java types in the injected code. This makes testing and injected code simpler.
*
* @param name the name of the span
* @return a {@link Closeable} to close the span
*/
public static Closeable span(final String name) {
try {
final ITraceProvider plugin = SETTINGS.getPlugin(ITraceProvider.class);
if (plugin == null) {
return () -> {
};
}
final ISpan span = plugin.createSpan(name);

if (span == null) {
return () -> {
};
}
return () -> {
try {
span.close();
} catch (Throwable t) {
LOGGER.error("Cannot close span: {}", name, t);
}
};
} catch (Throwable t) {
LOGGER.error("Cannot create span: {}", name, t);
return () -> {
};
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ public byte[] transform(final ClassLoader loader,
className); // we use the method fileName as it strips all but the last of the internal class name for us
final Collection<TracePointConfig> matchedTracepoints = matchTracepoints(className,
shortClassName);
// no breakpoints for this class or any CF classes
// no breakpoints for this class or any CF/JSP classes
if (matchedTracepoints.isEmpty() && !this.classPrefixTracepoints.containsKey(CFM_CLASS_KEY)
&& !this.classPrefixTracepoints.containsKey(JSP_CLASS_KEY)) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,14 @@

package com.intergral.deep.agent.tracepoint.inst.asm;

import static org.objectweb.asm.Opcodes.ACC_ABSTRACT;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import org.objectweb.asm.Opcodes;

/**
* Utilities for transforming the classes.
Expand All @@ -31,6 +34,9 @@ public final class TransformerUtils {
private TransformerUtils() {
}

static final boolean ALLOW_LINE_NUMBERS = Boolean.getBoolean("deep.line.numbers");
static final int LINE_OFFSET = Integer.getInteger("deep.line.offset", 20000);
static final boolean USE_SYNTHETIC = Boolean.parseBoolean(System.getProperty("deep.use.synthetic", "false"));
private static final List<String> EXCLUDE_PACKAGES = Collections.emptyList();
private static final List<String> EXCLUDE_CONTAINS = Collections.emptyList();

Expand Down Expand Up @@ -124,4 +130,12 @@ public static boolean isExcludedClass(final String classname) {

return false;
}

static boolean isStatic(final int acc) {
return (acc & Opcodes.ACC_STATIC) == Opcodes.ACC_STATIC;
}

static boolean isAbstract(final int access) {
return (access & ACC_ABSTRACT) == ACC_ABSTRACT;
}
}
Loading