Skip to content

Commit

Permalink
Tidy up and prepare for productionization (#7)
Browse files Browse the repository at this point in the history
* Fix API change

* EOD

* Remove SNAPSHOT dependency

* Update spotless plugin version

* Add surefire plugin (tree reporter)

* First step towards productionization
  • Loading branch information
kittylyst authored Nov 17, 2023
1 parent 6daaca9 commit 8a345c3
Show file tree
Hide file tree
Showing 10 changed files with 157 additions and 56 deletions.
86 changes: 54 additions & 32 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
<version>1.0.0-SNAPSHOT</version>

<properties>
<!-- <maven.compiler.release>8</maven.compiler.release>-->
<!-- <maven.compiler.release>8</maven.compiler.release>-->
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<skip.spotless>false</skip.spotless>

<!-- Core dependencies versions -->
<runtimes.java.api.version>${project.version}</runtimes.java.api.version>
<runtimes.java.api.version>2.0.0</runtimes.java.api.version>
<apache.httpclient.version>4.5.14</apache.httpclient.version>
<apache.httpcore.version>4.4.16</apache.httpcore.version>
<apache.httpmime.version>4.5.14</apache.httpmime.version>
Expand All @@ -29,8 +29,9 @@
<!-- Plugins versions -->
<maven-assembly-plugin.version>3.5.0</maven-assembly-plugin.version>
<google-java-format.version>1.7</google-java-format.version>
<spotless-maven-plugin.version>1.31.3</spotless-maven-plugin.version>
<spotless-maven-plugin.version>2.29.0</spotless-maven-plugin.version>
<maven-surefire-plugin.version>3.0.0-M9</maven-surefire-plugin.version>
<surefire-tree-reporter.version>1.2.1</surefire-tree-reporter.version>
<jacoco-maven-plugin.version>0.8.8</jacoco-maven-plugin.version>
<maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version>
<maven-jar-plugin.version>3.3.0</maven-jar-plugin.version>
Expand Down Expand Up @@ -66,14 +67,14 @@
<version>${apache.httpmime.version}</version>
</dependency>

<!-- Tools jar -->
<!-- <dependency>-->
<!-- <groupId>com.sun</groupId>-->
<!-- <artifactId>tools</artifactId>-->
<!-- <scope>system</scope>-->
<!-- <systemPath>${toolsjar}</systemPath>-->
<!-- <version>1.8.0</version>-->
<!-- </dependency>-->
<!-- Tools jar -->
<!-- <dependency>-->
<!-- <groupId>com.sun</groupId>-->
<!-- <artifactId>tools</artifactId>-->
<!-- <scope>system</scope>-->
<!-- <systemPath>${toolsjar}</systemPath>-->
<!-- <version>1.8.0</version>-->
<!-- </dependency>-->

<!-- Test dependencies -->
<dependency>
Expand Down Expand Up @@ -104,30 +105,29 @@
<scope>test</scope>
</dependency>

<!-- Byte Buddy is used for testing the agent -->
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>${byte-buddy.version}</version>
<scope>test</scope>
</dependency>

<!-- Byte Buddy is used for testing the agent -->
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>${byte-buddy.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-agent</artifactId>
<version>${byte-buddy.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-agent</artifactId>
<version>${byte-buddy.version}</version>
<scope>test</scope>
</dependency>

</dependencies>
</dependencyManagement>

<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>runtimes-java-api</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>runtimes-java-api</artifactId>
</dependency>

<dependency>
<groupId>org.apache.httpcomponents</groupId>
Expand Down Expand Up @@ -243,13 +243,35 @@
<version>${maven-surefire-plugin.version}</version>
<configuration>
<excludedGroups>IntegrationTest</excludedGroups>
<!-- config for maven-surefire-junit5-tree-reporter -->
<reportFormat>plain</reportFormat>
<consoleOutputReporter>
<disable>true</disable>
</consoleOutputReporter>
<statelessTestsetInfoReporter implementation="org.apache.maven.plugin.surefire.extensions.junit5.JUnit5StatelessTestsetInfoTreeReporter">
<printStacktraceOnError>true</printStacktraceOnError>
<printStacktraceOnFailure>true</printStacktraceOnFailure>
<printStdoutOnError>true</printStdoutOnError>
<printStdoutOnFailure>true</printStdoutOnFailure>
<printStdoutOnSuccess>false</printStdoutOnSuccess>
<printStderrOnError>true</printStderrOnError>
<printStderrOnFailure>true</printStderrOnFailure>
<printStderrOnSuccess>false</printStderrOnSuccess>
</statelessTestsetInfoReporter>
</configuration>
<dependencies>
<dependency>
<groupId>me.fabriciorby</groupId>
<artifactId>maven-surefire-junit5-tree-reporter</artifactId>
<version>${surefire-tree-reporter.version}</version>
</dependency>
</dependencies>
</plugin>

<plugin>
<groupId>com.diffplug.spotless</groupId>
<artifactId>spotless-maven-plugin</artifactId>
<!-- <version>${spotless-maven-plugin.version}</version>-->
<!-- <version>${spotless-maven-plugin.version}</version>-->
<configuration>
<skip>${skip.spotless}</skip>
<!-- optional: limit format enforcement to just the files changed by this feature branch -->
Expand Down Expand Up @@ -279,8 +301,8 @@
<googleJavaFormat>
<version>${google-java-format.version}</version>
<style>GOOGLE</style>
<!-- <reflowLongStrings>true</reflowLongStrings>-->
<!-- <groupArtifact>com.google.googlejavaformat:google-java-format</groupArtifact>-->
<!-- <reflowLongStrings>true</reflowLongStrings>-->
<!-- <groupArtifact>com.google.googlejavaformat:google-java-format</groupArtifact>-->
</googleJavaFormat>

<!-- make sure every file has the following copyright header.
Expand Down
13 changes: 9 additions & 4 deletions src/main/java/com/redhat/insights/agent/AgentBasicReport.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
/* Copyright (C) Red Hat 2023 */
package com.redhat.insights.agent;

import com.redhat.insights.AbstractTopLevelReportBase;
import com.redhat.insights.InsightsSubreport;
import com.redhat.insights.config.InsightsConfiguration;
import com.redhat.insights.jars.ClasspathJarInfoSubreport;
import com.redhat.insights.logging.InsightsLogger;
import java.util.Collections;
import com.redhat.insights.reports.AbstractTopLevelReportBase;
import com.redhat.insights.reports.InsightsSubreport;
import java.util.HashMap;
import java.util.Map;

public class AgentBasicReport extends AbstractTopLevelReportBase {
Expand All @@ -17,7 +18,11 @@ private AgentBasicReport(
}

public static AgentBasicReport of(InsightsLogger logger, InsightsConfiguration configuration) {
return new AgentBasicReport(logger, configuration, Collections.emptyMap());
Map<String, InsightsSubreport> reports = new HashMap<>();
ClasspathJarInfoSubreport jarsReport = new ClasspathJarInfoSubreport(logger);
reports.put("jars", jarsReport);
reports.put("details", AgentSubreport.of(jarsReport));
return new AgentBasicReport(logger, configuration, reports);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,13 @@ public boolean isOptingOut() {
}
return false;
}

public boolean isDebug() {
return "true".equalsIgnoreCase(args.getOrDefault("debug", "false"));
}

@Override
public String toString() {
return "AgentConfiguration{" + "args=" + args + '}';
}
}
49 changes: 40 additions & 9 deletions src/main/java/com/redhat/insights/agent/AgentMain.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
/* Copyright (C) Red Hat 2023 */
package com.redhat.insights.agent;

import com.redhat.insights.InsightsReport;
import com.redhat.insights.InsightsReportController;
import com.redhat.insights.http.InsightsFileWritingClient;
import com.redhat.insights.http.InsightsHttpClient;
import com.redhat.insights.jars.JarInfo;
import com.redhat.insights.logging.InsightsLogger;
import com.redhat.insights.logging.JulLogger;
import com.redhat.insights.reports.InsightsReport;
import com.redhat.insights.tls.PEMSupport;
import java.lang.instrument.Instrumentation;
import java.nio.file.Files;
Expand All @@ -19,11 +20,14 @@
import java.util.concurrent.LinkedBlockingQueue;
import java.util.function.Supplier;

/** Main class for the agent. */
public final class AgentMain {
private final InsightsLogger logger;
private final AgentConfiguration configuration;
private final BlockingQueue<JarInfo> waitingJars;

private static boolean loaded = false;

private AgentMain(
InsightsLogger logger, AgentConfiguration configuration, BlockingQueue<JarInfo> jarsToSend) {
this.logger = logger;
Expand All @@ -39,8 +43,22 @@ public static void agentmain(String agentArgs, Instrumentation instrumentation)
startAgent(agentArgs, instrumentation);
}

/**
* Real entry point for the agent.
*
* @param agentArgs the agent argument string
* @param instrumentation the instrumentation object, only used for class notification
*/
public static void startAgent(String agentArgs, Instrumentation instrumentation) {
InsightsLogger logger = new JulLogger("AgentMain");
synchronized (AgentMain.class) {
if (loaded) {
logger.warning("Insights agent already loaded, skipping");
return;
}
loaded = true;
}

if (agentArgs == null || "".equals(agentArgs)) {
logger.error("Unable to start Red Hat Insights client: Need config arguments");
return;
Expand All @@ -59,10 +77,16 @@ public static void startAgent(String agentArgs, Instrumentation instrumentation)
instrumentation.addTransformer(noticer);
} catch (Throwable t) {
logger.error("Unable to start Red Hat Insights client", t);
return;
}
}

/**
* Parse the agent arguments from the form "key1=value1;key2=value2;..."
*
* @param logger
* @param agentArgs
* @return
*/
static Optional<AgentConfiguration> parseArgs(InsightsLogger logger, String agentArgs) {
Map<String, String> out = new HashMap<>();
for (String pair : agentArgs.split(";")) {
Expand All @@ -82,28 +106,35 @@ static Optional<AgentConfiguration> parseArgs(InsightsLogger logger, String agen
"Unable to start Red Hat Insights client: App requires a name for identification");
return Optional.empty();
}
logger.debug(config.toString());

if (!config.getMaybeAuthToken().isPresent()) {
Path certPath = Paths.get(config.getCertFilePath());
Path keyPath = Paths.get(config.getKeyFilePath());
if (!Files.exists(certPath) || !Files.exists(keyPath)) {
logger.error("Unable to start Red Hat Insights client: Missing certificate or key files");
return Optional.empty();
if (!out.containsKey("debug") || !"true".equals(out.get("debug"))) {
logger.error("Unable to start Red Hat Insights client: Missing certificate or key files");
return Optional.empty();
}
}
}

return Optional.of(config);
}

private void start() {
final InsightsReport simpleReport = AgentBasicReport.of(logger, configuration);
final InsightsReport report = AgentBasicReport.of(logger, configuration);
final PEMSupport pem = new PEMSupport(logger, configuration);

final Supplier<InsightsHttpClient> httpClientSupplier =
() -> new InsightsAgentHttpClient(logger, configuration, () -> pem.createTLSContext());
Supplier<InsightsHttpClient> httpClientSupplier;
if (configuration.isDebug()) {
httpClientSupplier = () -> new InsightsFileWritingClient(logger, configuration);
} else {
httpClientSupplier =
() -> new InsightsAgentHttpClient(logger, configuration, () -> pem.createTLSContext());
}
final InsightsReportController controller =
InsightsReportController.of(
logger, configuration, simpleReport, httpClientSupplier, waitingJars);
InsightsReportController.of(logger, configuration, report, httpClientSupplier, waitingJars);
controller.generate();
}
}
29 changes: 29 additions & 0 deletions src/main/java/com/redhat/insights/agent/AgentSubreport.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/* Copyright (C) Red Hat 2023 */
package com.redhat.insights.agent;

import com.fasterxml.jackson.databind.JsonSerializer;
import com.redhat.insights.jars.ClasspathJarInfoSubreport;
import com.redhat.insights.reports.AppInsightsReportSerializer;
import com.redhat.insights.reports.InsightsSubreport;

public class AgentSubreport implements InsightsSubreport {

private AgentSubreport() {}

public static InsightsSubreport of(ClasspathJarInfoSubreport jarsReport) {
return new AgentSubreport();
}

@Override
public void generateReport() {}

@Override
public String getVersion() {
return "1.0.0";
}

@Override
public JsonSerializer<InsightsSubreport> getSerializer() {
return new AppInsightsReportSerializer();
}
}
12 changes: 9 additions & 3 deletions src/main/java/com/redhat/insights/agent/Attach.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
/* Copyright (C) Red Hat 2023 */
package com.redhat.insights.agent;

import com.sun.tools.attach.AgentInitializationException;
import com.sun.tools.attach.AgentLoadException;
import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.VirtualMachine;
import java.io.IOException;
import java.net.URL;

/** Dynamic attachment class for use on apps that are already running. */
public class Attach {
public static void main(String[] args) {
if (args.length < 2) {
System.err.println("Need args: pid, options"); // , path to agent
System.err.println("Need args: pid, options");
System.exit(1);
}
URL jarUrl = AgentMain.class.getProtectionDomain().getCodeSource().getLocation();
Expand All @@ -16,13 +21,14 @@ public static void main(String[] args) {

String pid = args[0];
String options = args[1];
// String agentJar = args[2];

try {
VirtualMachine vm = VirtualMachine.attach(pid);
vm.loadAgent(agentJar, options);
vm.detach();
} catch (Exception e) {
} catch (IOException e) {
// Probable Java version mismatch, ignore
} catch (AgentLoadException | AttachNotSupportedException | AgentInitializationException e) {
throw new RuntimeException(e);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/redhat/insights/agent/ClassNoticer.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import java.util.Set;
import java.util.concurrent.BlockingQueue;

public class ClassNoticer implements ClassFileTransformer {
public final class ClassNoticer implements ClassFileTransformer {
private final InsightsLogger logger;
private final BlockingQueue<JarInfo> jarsToSend;
private final JarAnalyzer analyzer;
Expand Down
Loading

0 comments on commit 8a345c3

Please sign in to comment.