Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
commit b84a73e
Merge: 352202f 7df9862
Author: SylvainJuge <[email protected]>
Date:   Tue Sep 17 11:13:11 2024 +0200

    Merge pull request #2 from SylvainJuge/jmx-scraper-it

    basic JMX client implementation + tests

commit 7df9862
Author: Sylvain Juge <[email protected]>
Date:   Tue Sep 17 11:11:50 2024 +0200

    fix bad merge again

commit e4a8f83
Author: Sylvain Juge <[email protected]>
Date:   Tue Sep 17 11:10:26 2024 +0200

    fix bad merge again

commit dad197b
Author: Sylvain Juge <[email protected]>
Date:   Tue Sep 17 11:09:18 2024 +0200

    fix bad merge

commit f8a73d7
Author: Sylvain Juge <[email protected]>
Date:   Tue Sep 17 11:08:42 2024 +0200

    spotless

commit eab01e9
Author: Sylvain Juge <[email protected]>
Date:   Tue Sep 17 11:01:47 2024 +0200

    spotless

commit f6667dd
Merge: 5b3ef9d 352202f
Author: Sylvain Juge <[email protected]>
Date:   Tue Sep 17 10:55:34 2024 +0200

    Merge branch 'jmx-scrapper' of github.com:SylvainJuge/opentelemetry-java-contrib into jmx-scraper-it

commit 5b3ef9d
Author: Sylvain Juge <[email protected]>
Date:   Tue Sep 17 10:51:11 2024 +0200

    add TODOs

commit 352202f
Merge: 5a82aac 40a2591
Author: SylvainJuge <[email protected]>
Date:   Tue Sep 17 10:50:50 2024 +0200

    Merge pull request #1 from robsunday/jmx-scrapper

    Initial commit of JmxScraper code.

commit 40a2591
Author: jack-berg <[email protected]>
Date:   Mon Sep 16 16:05:50 2024 -0500

    Add declarative config support for RuleBasedRoutingSampler (#1440)

commit 6d39e93
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Mon Sep 16 10:40:16 2024 -0700

    Update dependency com.uber.nullaway:nullaway to v0.11.3 (#1457)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

commit eb5dc6f
Author: Bruno Baptista <[email protected]>
Date:   Mon Sep 16 18:26:53 2024 +0100

    Fix native mode error cause by static init of random (#862)

commit 5ffa348
Author: jack-berg <[email protected]>
Date:   Mon Sep 16 12:23:41 2024 -0500

    Add declarative config support for aws xray propagators (#1442)

commit 151b744
Author: SylvainJuge <[email protected]>
Date:   Mon Sep 16 19:23:19 2024 +0200

    add span stacktrace config option (#1414)

    Co-authored-by: jackshirazi <[email protected]>

commit 9ee5fb1
Author: Yury Bubnov <[email protected]>
Date:   Mon Sep 16 10:18:51 2024 -0700

    Issue-1034 Short XRay Trace (#1036)

commit 11a2e1a
Author: Jeffrey Chien <[email protected]>
Date:   Mon Sep 16 13:18:10 2024 -0400

    Fix Tomcat metric definitions to aggregate multiple MBeans. (#1366)

commit 9fa44be
Author: Pranav Sharma <[email protected]>
Date:   Mon Sep 16 11:22:32 2024 -0400

    Fix incorrect cloud.platform value for GCF (#1454)

commit 11f2111
Author: Peter Findeisen <[email protected]>
Date:   Mon Sep 16 08:21:46 2024 -0700

    Composite Samplers prototype (#1443)

    Co-authored-by: Otmar Ertl <[email protected]>

commit b3386de
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Mon Sep 16 08:20:44 2024 -0700

    Update plugin com.squareup.wire to v5.1.0 (#1452)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

commit 27b631d
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Mon Sep 16 08:20:21 2024 -0700

    Update errorProneVersion to v2.32.0 (#1453)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

commit 791df4b
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Mon Sep 16 09:50:03 2024 -0500

    Update dependency io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha to v2.8.0-alpha (#1456)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
    Co-authored-by: Jack Berg <[email protected]>

commit 19357e6
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Tue Sep 10 15:20:46 2024 -0700

    Update dependency com.gradle.enterprise:com.gradle.enterprise.gradle.plugin to v3.18.1 (#1450)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

commit 460470b
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Tue Sep 10 15:20:23 2024 -0700

    Update plugin com.gradle.develocity to v3.18.1 (#1451)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

commit b45cdab
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Tue Sep 10 12:32:56 2024 +0300

    Update dependency com.linecorp.armeria:armeria-bom to v1.30.1 (#1449)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

commit d36106e
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Tue Sep 10 09:11:26 2024 +0300

    Update micrometer packages to v1.13.4 (#1448)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

commit fb25c79
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Mon Sep 9 15:44:53 2024 +0300

    Update dependency gradle to v8.10.1 (#1447)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

commit f847561
Author: robsunday <[email protected]>
Date:   Tue Sep 17 09:22:21 2024 +0200

    Code review changes:
    Argument parsing moved to the main class.
    Argument validation now throw exception.
    More tests added for config factory.
    Created unit tests for JmxScraper class.

commit 03788ff
Author: Sylvain Juge <[email protected]>
Date:   Mon Sep 16 17:26:12 2024 +0200

    add TODO for testing server SSL support

commit a3fbeb5
Author: Sylvain Juge <[email protected]>
Date:   Mon Sep 16 17:08:16 2024 +0200

    add TODO to enable server-side SSL

commit 1619595
Author: Sylvain Juge <[email protected]>
Date:   Mon Sep 16 16:59:17 2024 +0200

    wip

commit 164679f
Author: robsunday <[email protected]>
Date:   Wed Sep 11 12:34:12 2024 +0200

    Cleanup of config.
    Refactoring of JmxScraperConfigFactory.
    Added first unit tests.

commit 165fcb8
Author: robsunday <[email protected]>
Date:   Tue Sep 10 12:36:29 2024 +0200

    Initial commit of JmxScraper code. Application compiles and runs as standalone and can read config file.
  • Loading branch information
SylvainJuge committed Sep 17, 2024
1 parent d623abe commit f7b5a31
Show file tree
Hide file tree
Showing 5 changed files with 486 additions and 0 deletions.
21 changes: 21 additions & 0 deletions jmx-scraper/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,17 @@ dependencies {
testImplementation("org.junit-pioneer:junit-pioneer")
}

testing {
suites {
val integrationTest by registering(JvmTestSuite::class) {
dependencies {
implementation("org.testcontainers:junit-jupiter")
implementation("org.slf4j:slf4j-simple")
}
}
}
}

tasks {
shadowJar {
mergeServiceFiles()
Expand All @@ -40,7 +51,9 @@ tasks {

withType<Test>().configureEach {
dependsOn(shadowJar)
dependsOn(named("appJar"))
systemProperty("shadow.jar.path", shadowJar.get().archiveFile.get().asFile.absolutePath)
systemProperty("app.jar.path", named<Jar>("appJar").get().archiveFile.get().asFile.absolutePath)
systemProperty("gradle.project.version", "${project.version}")
}

Expand All @@ -52,6 +65,14 @@ tasks {
}
}

tasks.register<Jar>("appJar") {
from(sourceSets.get("integrationTest").output)
archiveClassifier.set("app")
manifest {
attributes["Main-Class"] = "io.opentelemetry.contrib.jmxscraper.TestApp"
}
}

// Don't publish non-shadowed jar (shadowJar is in shadowRuntimeElements)
with(components["java"] as AdhocComponentWithVariants) {
configurations.forEach {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.contrib.jmxscraper;

import java.lang.management.ManagementFactory;
import javax.management.MBeanServer;
import javax.management.ObjectName;

@SuppressWarnings("all")
public class TestApp implements TestAppMXBean {

public static final String APP_STARTED_MSG = "app started";
public static final String OBJECT_NAME = "io.opentelemetry.test:name=TestApp";

private volatile boolean running;

public static void main(String[] args) {
TestApp app = TestApp.start();
while (app.isRunning()) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}

private TestApp() {}

static TestApp start() {
TestApp app = new TestApp();
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
try {
ObjectName objectName = new ObjectName(OBJECT_NAME);
mbs.registerMBean(app, objectName);
} catch (Exception e) {
throw new RuntimeException(e);
}
app.running = true;
System.out.println(APP_STARTED_MSG);
return app;
}

@Override
public int getIntValue() {
return 42;
}

@Override
public void stopApp() {
running = false;
}

boolean isRunning() {
return running;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.contrib.jmxscraper;

@SuppressWarnings("unused")
public interface TestAppMXBean {

int getIntValue();

void stopApp();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.contrib.jmxscraper.client;

import static org.assertj.core.api.Assertions.assertThat;

import io.opentelemetry.contrib.jmxscraper.TestApp;
import java.io.Closeable;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Duration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.output.Slf4jLogConsumer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.shaded.com.google.errorprone.annotations.CanIgnoreReturnValue;
import org.testcontainers.utility.MountableFile;

public class JmxRemoteClientTest {

private static final Logger logger = LoggerFactory.getLogger(JmxRemoteClientTest.class);

private static Network network;

private static final List<AutoCloseable> toClose = new ArrayList<>();

@BeforeAll
static void beforeAll() {
network = Network.newNetwork();
toClose.add(network);
}

@AfterAll
static void afterAll() {
for (AutoCloseable item : toClose) {
try {
item.close();
} catch (Exception e) {
logger.warn("Error closing " + item, e);
}
}
}

@Test
void noAuth() {
try (AppContainer app = new AppContainer().withJmxPort(9990).start()) {
testConnector(() -> JmxRemoteClient.createNew(app.getHost(), app.getPort()).connect());
}
}

@Test
void loginPwdAuth() {
String login = "user";
String pwd = "t0p!Secret";
try (AppContainer app = new AppContainer().withJmxPort(9999).withUserAuth(login, pwd).start()) {
testConnector(
() ->
JmxRemoteClient.createNew(app.getHost(), app.getPort())
.userCredentials(login, pwd)
.connect());
}
}

@Test
void serverSSL() {
// TODO: test with SSL enabled as RMI registry seems to work differently with SSL

// create keypair (public,private)
// create server keystore with private key
// configure server keystore
//
// create client truststore with public key
// can we configure to use a custom truststore ???
// connect to server
}

private static void testConnector(ConnectorSupplier connectorSupplier) {
try (JMXConnector connector = connectorSupplier.get()) {
assertThat(connector.getMBeanServerConnection())
.isNotNull()
.satisfies(
connection -> {
try {
ObjectName name = new ObjectName(TestApp.OBJECT_NAME);
Object value = connection.getAttribute(name, "IntValue");
assertThat(value).isEqualTo(42);
} catch (Exception e) {
throw new RuntimeException(e);
}
});

} catch (IOException e) {
throw new RuntimeException(e);
}
}

private interface ConnectorSupplier {
JMXConnector get() throws IOException;
}

private static class AppContainer implements Closeable {

private final GenericContainer<?> appContainer;
private final Map<String, String> properties;
private int port;
private String login;
private String pwd;

private AppContainer() {
this.properties = new HashMap<>();

properties.put("com.sun.management.jmxremote.ssl", "false"); // TODO :

// SSL registry : com.sun.management.jmxremote.registry.ssl
// client side ssl auth: com.sun.management.jmxremote.ssl.need.client.auth

String appJar = System.getProperty("app.jar.path");
assertThat(Paths.get(appJar)).isNotEmptyFile().isReadable();

this.appContainer =
new GenericContainer<>("openjdk:8u272-jre-slim")
.withCopyFileToContainer(MountableFile.forHostPath(appJar), "/app.jar")
.withLogConsumer(new Slf4jLogConsumer(logger))
.withNetwork(network)
.waitingFor(
Wait.forLogMessage(TestApp.APP_STARTED_MSG + "\\n", 1)
.withStartupTimeout(Duration.ofSeconds(5)))
.withCommand("java", "-jar", "/app.jar");
}

@CanIgnoreReturnValue
public AppContainer withJmxPort(int port) {
this.port = port;
properties.put("com.sun.management.jmxremote.port", Integer.toString(port));
appContainer.withExposedPorts(port);
return this;
}

@CanIgnoreReturnValue
public AppContainer withUserAuth(String login, String pwd) {
this.login = login;
this.pwd = pwd;
return this;
}

@CanIgnoreReturnValue
AppContainer start() {
if (pwd == null) {
properties.put("com.sun.management.jmxremote.authenticate", "false");
} else {
properties.put("com.sun.management.jmxremote.authenticate", "true");

Path pwdFile = createPwdFile(login, pwd);
appContainer.withCopyFileToContainer(MountableFile.forHostPath(pwdFile), "/jmx.password");
properties.put("com.sun.management.jmxremote.password.file", "/jmx.password");

Path accessFile = createAccessFile(login);
appContainer.withCopyFileToContainer(MountableFile.forHostPath(accessFile), "/jmx.access");
properties.put("com.sun.management.jmxremote.access.file", "/jmx.access");
}

String confArgs =
properties.entrySet().stream()
.map(
e -> {
String s = "-D" + e.getKey();
if (!e.getValue().isEmpty()) {
s += "=" + e.getValue();
}
return s;
})
.collect(Collectors.joining(" "));

appContainer.withEnv("JAVA_TOOL_OPTIONS", confArgs).start();

logger.info("Test application JMX port mapped to {}:{}", getHost(), getPort());

toClose.add(this);
return this;
}

int getPort() {
return appContainer.getMappedPort(port);
}

String getHost() {
return appContainer.getHost();
}

@Override
public void close() {
if (appContainer.isRunning()) {
appContainer.stop();
}
}

private static Path createPwdFile(String login, String pwd) {
try {
Path path = Files.createTempFile("test", ".pwd");
writeLine(path, String.format("%s %s", login, pwd));
return path;
} catch (IOException e) {
throw new RuntimeException(e);
}
}

private static Path createAccessFile(String login) {
try {
Path path = Files.createTempFile("test", ".pwd");
writeLine(path, String.format("%s %s", login, "readwrite"));
return path;
} catch (IOException e) {
throw new RuntimeException(e);
}
}

private static void writeLine(Path path, String line) throws IOException {
line = line + "\n";
Files.write(path, line.getBytes(StandardCharsets.UTF_8));
}
}
}
Loading

0 comments on commit f7b5a31

Please sign in to comment.