diff --git a/agent/pom.xml b/agent/pom.xml new file mode 100644 index 0000000..f5b0d24 --- /dev/null +++ b/agent/pom.xml @@ -0,0 +1,191 @@ + + + 4.0.0 + + io.github.dpsoft + ap-agent + 0.1.2-SNAPSHOT + jar + + + 2.9-4 + 0.10.3 + 1.4.2 + 2.5.0 + 0.0.2-SNAPSHOT + 11 + 11 + 11 + + + + + oss-snapshots + Oss Snapshots + https://s01.oss.sonatype.org/content/repositories/snapshots/ + + + maven-central + Maven central + https://repo.maven.apache.org/maven2/ + + + local + Maven local + file:////home/diego/.m2/repository + + + + + + me.bechberger + ap-loader-all + ${me.bechberger.ap-loader.version} + + + io.vavr + vavr + ${io.vavr.version} + + + com.typesafe + config + ${com.typesafe.config.version} + + + org.tinylog + tinylog-api + ${org.tinylog.version} + + + org.tinylog + tinylog-impl + ${org.tinylog.version} + + + me.bechberger + jfrtofp + ${me.bechberger.version} + + + io.github.dpsoft + context-api + 0.1.2-SNAPSHOT + provided + + + + + + src/main/resources + true + + **/build-info.properties + + + + src/main/resources + false + + **/build-info.properties + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.4.1 + + + package + + shade + + + true + ${project.build.directory}/dependency-reduced-pom.xml + true + + + org.codehaus.mojo + + + + + + io.github.dpsoft.ap.Agent + + + + + + + *:* + + META-INF/maven/** + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + META-INF/*.md + META-INF/LICENSE + + + + + + com.typesafe.config + io.github.dpsoft.ap.libs.com.typesafe.config + + + io.vavr + io.github.dpsoft.ap.libs.io.vavr + + + org.tinylog + io.github.dpsoft.ap.libs.org.tinylog + + + one + io.github.dpsoft.ap.libs.one + + + dev.dirs + io.github.dpsoft.ap.libs.dev.dirs + + + me.bechberger + io.github.dpsoft.ap.libs.me.bechberger + + + kotlin + io.github.dpsoft.ap.libs.kotlin + + + kotlinx + io.github.dpsoft.ap.libs.kotlinx + + + org.jetbrains + io.github.dpsoft.ap.libs.org.jetbrains + + + org.jline + io.github.dpsoft.ap.libs.org.jline + + + org.objectweb + io.github.dpsoft.ap.libs.org.objectweb + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/io/github/dpsoft/ap/Agent.java b/agent/src/main/java/io/github/dpsoft/ap/Agent.java similarity index 97% rename from src/main/java/io/github/dpsoft/ap/Agent.java rename to agent/src/main/java/io/github/dpsoft/ap/Agent.java index 442241f..179bb63 100644 --- a/src/main/java/io/github/dpsoft/ap/Agent.java +++ b/agent/src/main/java/io/github/dpsoft/ap/Agent.java @@ -1,14 +1,14 @@ package io.github.dpsoft.ap; -import io.github.dpsoft.ap.handler.AsyncProfilerHandler; import io.github.dpsoft.ap.util.Banner; import io.github.dpsoft.ap.util.Runner; import io.github.dpsoft.ap.util.Server; +import io.github.dpsoft.ap.handler.AsyncProfilerHandler; import java.lang.instrument.Instrumentation; public final class Agent { - public static void premain(String args, Instrumentation inst) { + public static void premain(String args, Instrumentation instrumentation) { Runner.runWith((profiler, configuration) -> { Banner.show(configuration); diff --git a/src/main/java/io/github/dpsoft/ap/command/Command.java b/agent/src/main/java/io/github/dpsoft/ap/command/Command.java similarity index 100% rename from src/main/java/io/github/dpsoft/ap/command/Command.java rename to agent/src/main/java/io/github/dpsoft/ap/command/Command.java diff --git a/src/main/java/io/github/dpsoft/ap/config/AgentConfiguration.java b/agent/src/main/java/io/github/dpsoft/ap/config/AgentConfiguration.java similarity index 99% rename from src/main/java/io/github/dpsoft/ap/config/AgentConfiguration.java rename to agent/src/main/java/io/github/dpsoft/ap/config/AgentConfiguration.java index 050f09f..2a19f2f 100644 --- a/src/main/java/io/github/dpsoft/ap/config/AgentConfiguration.java +++ b/agent/src/main/java/io/github/dpsoft/ap/config/AgentConfiguration.java @@ -14,6 +14,7 @@ public final class AgentConfiguration { public final Handler handler; public final boolean showBanner; + private AgentConfiguration(Config config) { this.server = new Server(config); this.handler = new Handler(config); diff --git a/agent/src/main/java/io/github/dpsoft/ap/context/APContextListener.java b/agent/src/main/java/io/github/dpsoft/ap/context/APContextListener.java new file mode 100644 index 0000000..1369390 --- /dev/null +++ b/agent/src/main/java/io/github/dpsoft/ap/context/APContextListener.java @@ -0,0 +1,18 @@ +package io.github.dpsoft.ap.context; + +import io.github.dpsoft.ap.context.api.context.Context; +import io.github.dpsoft.ap.context.api.storage.ContextStorageListener; + +/** + * This listener is used to store the current context id in AsyncProfiler and restore it when the context is restored. + */ +public final class APContextListener implements ContextStorageListener { + @Override + public void onContextStored(Context context) { + System.out.println("stored::AsyncProfiler.setContextId(" + context.get(Context.ContextID) + ")"); + } + @Override + public void onContextRestored(Context context) { + System.out.println("restored::AsyncProfiler.setContextId(" + context.get(Context.ContextID) + ")"); + } +} diff --git a/src/main/java/io/github/dpsoft/ap/converters/experimental/hotcold/HotColdFlameGraph.java b/agent/src/main/java/io/github/dpsoft/ap/converters/experimental/hotcold/HotColdFlameGraph.java similarity index 100% rename from src/main/java/io/github/dpsoft/ap/converters/experimental/hotcold/HotColdFlameGraph.java rename to agent/src/main/java/io/github/dpsoft/ap/converters/experimental/hotcold/HotColdFlameGraph.java diff --git a/src/main/java/io/github/dpsoft/ap/converters/experimental/hotcold/jfr2hotcoldflame.java b/agent/src/main/java/io/github/dpsoft/ap/converters/experimental/hotcold/jfr2hotcoldflame.java similarity index 100% rename from src/main/java/io/github/dpsoft/ap/converters/experimental/hotcold/jfr2hotcoldflame.java rename to agent/src/main/java/io/github/dpsoft/ap/converters/experimental/hotcold/jfr2hotcoldflame.java diff --git a/src/main/java/io/github/dpsoft/ap/converters/experimental/package-info.java b/agent/src/main/java/io/github/dpsoft/ap/converters/experimental/package-info.java similarity index 100% rename from src/main/java/io/github/dpsoft/ap/converters/experimental/package-info.java rename to agent/src/main/java/io/github/dpsoft/ap/converters/experimental/package-info.java diff --git a/src/main/java/io/github/dpsoft/ap/functions/Functions.java b/agent/src/main/java/io/github/dpsoft/ap/functions/Functions.java similarity index 100% rename from src/main/java/io/github/dpsoft/ap/functions/Functions.java rename to agent/src/main/java/io/github/dpsoft/ap/functions/Functions.java diff --git a/src/main/java/io/github/dpsoft/ap/handler/AsyncProfilerHandler.java b/agent/src/main/java/io/github/dpsoft/ap/handler/AsyncProfilerHandler.java similarity index 100% rename from src/main/java/io/github/dpsoft/ap/handler/AsyncProfilerHandler.java rename to agent/src/main/java/io/github/dpsoft/ap/handler/AsyncProfilerHandler.java diff --git a/src/main/java/io/github/dpsoft/ap/util/Banner.java b/agent/src/main/java/io/github/dpsoft/ap/util/Banner.java similarity index 100% rename from src/main/java/io/github/dpsoft/ap/util/Banner.java rename to agent/src/main/java/io/github/dpsoft/ap/util/Banner.java diff --git a/src/main/java/io/github/dpsoft/ap/util/BuildInfo.java b/agent/src/main/java/io/github/dpsoft/ap/util/BuildInfo.java similarity index 100% rename from src/main/java/io/github/dpsoft/ap/util/BuildInfo.java rename to agent/src/main/java/io/github/dpsoft/ap/util/BuildInfo.java diff --git a/src/main/java/io/github/dpsoft/ap/util/ProfilerExecutor.java b/agent/src/main/java/io/github/dpsoft/ap/util/ProfilerExecutor.java similarity index 100% rename from src/main/java/io/github/dpsoft/ap/util/ProfilerExecutor.java rename to agent/src/main/java/io/github/dpsoft/ap/util/ProfilerExecutor.java diff --git a/src/main/java/io/github/dpsoft/ap/util/Runner.java b/agent/src/main/java/io/github/dpsoft/ap/util/Runner.java similarity index 100% rename from src/main/java/io/github/dpsoft/ap/util/Runner.java rename to agent/src/main/java/io/github/dpsoft/ap/util/Runner.java diff --git a/src/main/java/io/github/dpsoft/ap/util/Server.java b/agent/src/main/java/io/github/dpsoft/ap/util/Server.java similarity index 100% rename from src/main/java/io/github/dpsoft/ap/util/Server.java rename to agent/src/main/java/io/github/dpsoft/ap/util/Server.java diff --git a/src/main/java/io/github/dpsoft/ap/util/StrSubstitutor.java b/agent/src/main/java/io/github/dpsoft/ap/util/StrSubstitutor.java similarity index 100% rename from src/main/java/io/github/dpsoft/ap/util/StrSubstitutor.java rename to agent/src/main/java/io/github/dpsoft/ap/util/StrSubstitutor.java diff --git a/src/main/java/one/converter/Arguments.java b/agent/src/main/java/one/converter/Arguments.java similarity index 100% rename from src/main/java/one/converter/Arguments.java rename to agent/src/main/java/one/converter/Arguments.java diff --git a/src/main/java/one/converter/CollapsedStacks.java b/agent/src/main/java/one/converter/CollapsedStacks.java similarity index 100% rename from src/main/java/one/converter/CollapsedStacks.java rename to agent/src/main/java/one/converter/CollapsedStacks.java diff --git a/agent/src/main/resources/META-INF/services/io.github.dpsoft.ap.context.api.storage.ContextStorageListener b/agent/src/main/resources/META-INF/services/io.github.dpsoft.ap.context.api.storage.ContextStorageListener new file mode 100644 index 0000000..dc2b79c --- /dev/null +++ b/agent/src/main/resources/META-INF/services/io.github.dpsoft.ap.context.api.storage.ContextStorageListener @@ -0,0 +1 @@ +io.github.dpsoft.ap.context.APContextListener \ No newline at end of file diff --git a/src/main/resources/banner.txt b/agent/src/main/resources/banner.txt similarity index 100% rename from src/main/resources/banner.txt rename to agent/src/main/resources/banner.txt diff --git a/src/main/resources/build-info.properties b/agent/src/main/resources/build-info.properties similarity index 100% rename from src/main/resources/build-info.properties rename to agent/src/main/resources/build-info.properties diff --git a/src/main/resources/reference.conf b/agent/src/main/resources/reference.conf similarity index 85% rename from src/main/resources/reference.conf rename to agent/src/main/resources/reference.conf index a573ad5..0c315ca 100644 --- a/src/main/resources/reference.conf +++ b/agent/src/main/resources/reference.conf @@ -9,6 +9,7 @@ ap-agent { port: 8080 } + # The agent will recive requests on this path handler { go-mode: false go-context: "/debug/pprof/profile" diff --git a/src/main/resources/tinylog.properties b/agent/src/main/resources/tinylog.properties similarity index 100% rename from src/main/resources/tinylog.properties rename to agent/src/main/resources/tinylog.properties diff --git a/agent/src/test/resources/application.conf b/agent/src/test/resources/application.conf new file mode 100644 index 0000000..1030035 --- /dev/null +++ b/agent/src/test/resources/application.conf @@ -0,0 +1,10 @@ +ap-agent { + + #The agent banner will be shown on the console + show-banner = false + + # Bytecode instrumentation is disabled by default + context-instrumenter { + enabled = true + } +} \ No newline at end of file diff --git a/context-api/pom.xml b/context-api/pom.xml new file mode 100644 index 0000000..9b1f36d --- /dev/null +++ b/context-api/pom.xml @@ -0,0 +1,23 @@ + + 4.0.0 + + io.github.dpsoft + context-api + 0.1.2-SNAPSHOT + jar + + + + org.junit.jupiter + junit-jupiter + 5.9.2 + test + + + + + 11 + 11 + 11 + + \ No newline at end of file diff --git a/context-api/src/main/java/io/github/dpsoft/ap/context/api/ContextHandler.java b/context-api/src/main/java/io/github/dpsoft/ap/context/api/ContextHandler.java new file mode 100644 index 0000000..0f53108 --- /dev/null +++ b/context-api/src/main/java/io/github/dpsoft/ap/context/api/ContextHandler.java @@ -0,0 +1,42 @@ +package io.github.dpsoft.ap.context.api; + + +import io.github.dpsoft.ap.context.api.context.Context; +import io.github.dpsoft.ap.context.api.storage.ContextStorage; +import io.github.dpsoft.ap.context.api.storage.Storage; + +import java.util.function.Supplier; + +/** + * This class is used to store and retrieve the current context. + * Its implementation is Noop by default, but it can be replaced by an agent in runtime. + */ +public class ContextHandler { + /** + * Returns the current context. + */ + public static Context currentContext() { return ContextStorage.INSTANCE.currentContext();} + /** + * Stores the current context and returns a scope that can be used to restore it. + */ + public static Storage.Scope storeContext(Context context) { return ContextStorage.INSTANCE.storeContext(context);} + + /** + * Runs the given supplier with the given context. + * The context is restored after the supplier returns. + */ + public static T runWithContext(Context context, Supplier supplier) { + try (var ignored = storeContext(context)) { + return supplier.get(); + } + } + /** + * Runs the given runnable with the given context. + * The context is restored after the runnable returns. + */ + public static void runWitContext(Context context, Runnable runnable) { + try (var ignored = storeContext(context)) { + runnable.run(); + } + } +} diff --git a/context-api/src/main/java/io/github/dpsoft/ap/context/api/context/Context.java b/context-api/src/main/java/io/github/dpsoft/ap/context/api/context/Context.java new file mode 100644 index 0000000..7e929b1 --- /dev/null +++ b/context-api/src/main/java/io/github/dpsoft/ap/context/api/context/Context.java @@ -0,0 +1,66 @@ +package io.github.dpsoft.ap.context.api.context; + +import java.util.HashMap; +import java.util.Map; + +public final class Context { + public static final Context EMPTY = new Context(Map.of(), Labels.EMPTY); + + public static final Context.Key ContextID = new Context.Key<>("contextId", 0L); + + private final Map underlying; + + private final Labels labels; + + public static Context of(Labels labels) { + return new Context(Map.of(), labels); + } + + public static Context of(Context.Key key, T value) { + return new Context(Map.of(key.name, value), Labels.EMPTY); + } + + public static Context of(Context.Key key, T value, Labels labels) { + return new Context(Map.of(key.name, value), labels); + } + + private Context(Map underling, Labels labels) { + this.labels = labels; + this.underlying = underling; + } + + public Context withEntry(Context.Key key, T value) { + var x = new HashMap(underlying.size() + 1); + x.putAll(underlying); + x.put(key.name, value); + + return new Context(x, labels); + } + + public Context withTag(String key, String value) { + return new Context(underlying, labels.withLabel(key, value)); + } + + public Labels labels() { + return labels; + } + + + public T get(Context.Key key) { + return (T) underlying.getOrDefault(key.name, key.emptyValue); + } + + public static Context.Key key(String name, T emptyValue) { + return new Context.Key<>(name, emptyValue); + } + + public static class Key { + public final String name; + public final T emptyValue; + + public Key(String name, T emptyValue) { + this.name = name; + this.emptyValue = emptyValue; + } + } +} \ No newline at end of file diff --git a/context-api/src/main/java/io/github/dpsoft/ap/context/api/context/Labels.java b/context-api/src/main/java/io/github/dpsoft/ap/context/api/context/Labels.java new file mode 100644 index 0000000..ff945e1 --- /dev/null +++ b/context-api/src/main/java/io/github/dpsoft/ap/context/api/context/Labels.java @@ -0,0 +1,62 @@ +package io.github.dpsoft.ap.context.api.context; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +public final class Labels { + public final static Labels EMPTY = new Labels(Map.of()); + private final Map underlying; + + private Labels(Map underlying) { + this.underlying = underlying; + } + + public static Labels from(Map underlying) { + return new Labels(underlying); + } + + public static Labels of(String key, String value) { + return new Labels(Map.of(key, value)); + } + + public Labels withLabel(String key, String value) { + var mergedMap = new HashMap(underlying.size() + 1); + mergedMap.putAll(underlying); + mergedMap.put(key, value); + + return new Labels(mergedMap); + } + + public Set