Skip to content

Expose server config, session queue and node as MBeans for JMX monitoring. #8838

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Dec 22, 2020
1 change: 1 addition & 0 deletions java/server/src/org/openqa/selenium/grid/node/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ java_library(
"//java/server/src/org/openqa/selenium/grid/security",
"//java/server/src/org/openqa/selenium/grid/web",
"//java/server/src/org/openqa/selenium/status",
"//java/server/src/org/openqa/selenium/remote/server/jmx",
artifact("com.google.guava:guava"),
],
)
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ java_library(
"//java/server/src/org/openqa/selenium/grid/node/config",
"//java/server/src/org/openqa/selenium/grid/security",
"//java/server/src/org/openqa/selenium/grid/server",
"//java/server/src/org/openqa/selenium/remote/server/jmx",
artifact("com.google.guava:guava"),
],
)
50 changes: 50 additions & 0 deletions java/server/src/org/openqa/selenium/grid/node/local/LocalNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.concurrent.Regularly;
import org.openqa.selenium.events.EventBus;
import org.openqa.selenium.grid.data.Availability;
import org.openqa.selenium.grid.data.CreateSessionRequest;
import org.openqa.selenium.grid.data.CreateSessionResponse;
import org.openqa.selenium.grid.data.NodeDrainComplete;
Expand All @@ -53,6 +54,9 @@
import org.openqa.selenium.remote.SessionId;
import org.openqa.selenium.remote.http.HttpRequest;
import org.openqa.selenium.remote.http.HttpResponse;
import org.openqa.selenium.remote.server.jmx.JMXHelper;
import org.openqa.selenium.remote.server.jmx.ManagedAttribute;
import org.openqa.selenium.remote.server.jmx.ManagedService;
import org.openqa.selenium.remote.tracing.AttributeKey;
import org.openqa.selenium.remote.tracing.EventAttribute;
import org.openqa.selenium.remote.tracing.EventAttributeValue;
Expand Down Expand Up @@ -91,6 +95,8 @@
import static org.openqa.selenium.remote.http.Contents.string;
import static org.openqa.selenium.remote.http.HttpMethod.DELETE;

@ManagedService(objectName = "org.seleniumhq.grid:type=Node,name=LocalNode",
description = "Node running the webdriver sessions.")
public class LocalNode extends Node {

private static final Json JSON = new Json();
Expand Down Expand Up @@ -173,6 +179,8 @@ private LocalNode(
}
}
}));

new JMXHelper().register(this);
}

@Override
Expand All @@ -181,11 +189,53 @@ public boolean isReady() {
}

@VisibleForTesting
@ManagedAttribute(name = "CurrentSessions")
public int getCurrentSessionCount() {
// It seems wildly unlikely we'll overflow an int
return Math.toIntExact(currentSessions.size());
}

@ManagedAttribute(name = "MaxSessions")
public int getMaxSessionCount() {
return maxSessionCount;
}

@ManagedAttribute(name = "Status")
public Availability getAvailability() {
return isDraining() ? DRAINING : UP;
}

@ManagedAttribute(name = "TotalSlots")
public int getTotalSlots() {
return factories.size();
}

@ManagedAttribute(name = "UsedSlots")
public long getUsedSlots() {
return factories.stream().filter(sessionSlot -> !sessionSlot.isAvailable()).count();
}

@ManagedAttribute(name = "Load")
public float getLoad() {
long inUse = factories.stream().filter(sessionSlot -> !sessionSlot.isAvailable()).count();
return inUse / (float) maxSessionCount * 100f;
}

@ManagedAttribute(name = "RemoteNodeUri")
public URI getExternalUri() {
return this.getUri();
}

@ManagedAttribute(name = "GridUri")
public URI getGridUri() {
return this.gridUri;
}

@ManagedAttribute(name = "NodeId")
public String getNodeId() {
return getId().toString();
}

@Override
public boolean isSupporting(Capabilities capabilities) {
return factories.parallelStream().anyMatch(factory -> factory.test(capabilities));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ java_library(
"//java/server/src/org/openqa/selenium/grid/component",
"//java/server/src/org/openqa/selenium/grid/config",
"//java/server/src/org/openqa/selenium/grid/web",
"//java/server/src/org/openqa/selenium/remote/server/jmx",
artifact("com.beust:jcommander"),
artifact("com.google.guava:guava"),
artifact("javax.servlet:javax.servlet-api"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,18 @@
import org.openqa.selenium.net.HostIdentifier;
import org.openqa.selenium.net.NetworkUtils;
import org.openqa.selenium.net.PortProber;
import org.openqa.selenium.remote.server.jmx.JMXHelper;
import org.openqa.selenium.remote.server.jmx.ManagedAttribute;
import org.openqa.selenium.remote.server.jmx.ManagedService;

import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Optional;
import java.util.logging.Logger;

@ManagedService(objectName = "org.seleniumhq.grid:type=Config,name=BaseServerConfig",
description = "Server config")
public class BaseServerOptions {

private static final String SERVER_SECTION = "server";
Expand All @@ -40,12 +45,14 @@ public class BaseServerOptions {

public BaseServerOptions(Config config) {
this.config = config;
new JMXHelper().register(this);
}

public Optional<String> getHostname() {
return config.get(SERVER_SECTION, "hostname");
}

@ManagedAttribute(name = "Port")
public int getPort() {
if (port == -1) {
int newPort = config.getInt(SERVER_SECTION, "port")
Expand All @@ -61,6 +68,7 @@ public int getPort() {
return port;
}

@ManagedAttribute(name = "MaxServerThreads")
public int getMaxServerThreads() {
int count = config.getInt(SERVER_SECTION, "max-threads")
.orElse(200);
Expand All @@ -72,6 +80,7 @@ public int getMaxServerThreads() {
return count;
}

@ManagedAttribute(name = "Uri")
public URI getExternalUri() {
// Assume the host given is addressable if it's been set
String host = getHostname()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ java_library(
"//java/server/src/org/openqa/selenium/grid/data",
"//java/server/src/org/openqa/selenium/grid/log",
"//java/server/src/org/openqa/selenium/status",
"//java/server/src/org/openqa/selenium/remote/server/jmx",
artifact("com.google.guava:guava"),
],
)
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ java_library(
srcs = glob(["*.java"]),
visibility = [
"//java/server/src/org/openqa/selenium/grid:__subpackages__",
"//java/server/test/org/openqa/selenium/grid:__subpackages__",
],
deps = [
"//java:auto-service",
"//java/server/src/org/openqa/selenium/grid/config",
"//java/server/src/org/openqa/selenium/grid/sessionqueue",
"//java/server/src/org/openqa/selenium/remote/server/jmx",
artifact("com.beust:jcommander"),
artifact("io.opentelemetry:opentelemetry-api"),
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,14 @@

import org.openqa.selenium.grid.config.Config;
import org.openqa.selenium.grid.sessionqueue.NewSessionQueue;
import org.openqa.selenium.remote.server.jmx.JMXHelper;
import org.openqa.selenium.remote.server.jmx.ManagedAttribute;
import org.openqa.selenium.remote.server.jmx.ManagedService;

import java.time.Duration;

@ManagedService(objectName = "org.seleniumhq.grid:type=Config,name=NewSessionQueueConfig",
description = "New session queue config")
public class NewSessionQueueOptions {

private static final String SESSIONS_QUEUE_SECTION = "sessionqueue";
Expand All @@ -35,10 +40,11 @@ public class NewSessionQueueOptions {

public NewSessionQueueOptions(Config config) {
this.config = config;
new JMXHelper().register(this);
}

public Duration getSessionRequestTimeout() {
int timeout = config.getInt(SESSIONS_QUEUE_SECTION, "session-request-timeout")
long timeout = config.getInt(SESSIONS_QUEUE_SECTION, "session-request-timeout")
.orElse(DEFAULT_REQUEST_TIMEOUT);

if (timeout <= 0) {
Expand All @@ -48,7 +54,7 @@ public Duration getSessionRequestTimeout() {
}

public Duration getSessionRequestRetryInterval() {
int interval = config.getInt(SESSIONS_QUEUE_SECTION, "session-retry-interval")
long interval = config.getInt(SESSIONS_QUEUE_SECTION, "session-retry-interval")
.orElse(DEFAULT_RETRY_INTERVAL);

if (interval <= 0) {
Expand All @@ -57,6 +63,16 @@ public Duration getSessionRequestRetryInterval() {
return Duration.ofSeconds(interval);
}

@ManagedAttribute(name = "RequestTimeoutSeconds")
public long getRequestTimeoutSeconds() {
return getSessionRequestTimeout().getSeconds();
}

@ManagedAttribute(name = "RetryIntervalSeconds")
public long getRetryIntervalSeconds() {
return getSessionRequestRetryInterval().getSeconds();
}

public NewSessionQueue getSessionQueue() {
return config
.getClass(SESSIONS_QUEUE_SECTION, "implementation", NewSessionQueue.class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ java_library(
"//java/server/src/org/openqa/selenium/grid/server",
"//java/server/src/org/openqa/selenium/grid/sessionqueue",
"//java/server/src/org/openqa/selenium/grid/sessionqueue/config",
"//java/server/src/org/openqa/selenium/remote/server/jmx",
artifact("com.google.guava:guava"),
],
)
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@
import org.openqa.selenium.grid.sessionqueue.config.NewSessionQueueOptions;
import org.openqa.selenium.internal.Require;
import org.openqa.selenium.remote.http.HttpRequest;

import org.openqa.selenium.remote.server.jmx.JMXHelper;
import org.openqa.selenium.remote.server.jmx.ManagedAttribute;
import org.openqa.selenium.remote.server.jmx.ManagedService;

import org.openqa.selenium.remote.tracing.AttributeKey;
import org.openqa.selenium.remote.tracing.EventAttribute;
import org.openqa.selenium.remote.tracing.EventAttributeValue;
Expand All @@ -50,6 +55,8 @@
import java.util.logging.Level;
import java.util.logging.Logger;

@ManagedService(objectName = "org.seleniumhq.grid:type=SessionQueue,name=LocalSessionQueue",
description = "New session queue")
public class LocalNewSessionQueue extends NewSessionQueue {

private static final Logger LOG = Logger.getLogger(LocalNewSessionQueue.class.getName());
Expand All @@ -65,6 +72,7 @@ public LocalNewSessionQueue(Tracer tracer, EventBus bus, Duration retryInterval,
super(tracer, retryInterval, requestTimeout);
this.bus = Require.nonNull("Event bus", bus);
Runtime.getRuntime().addShutdownHook(shutdownHook);
new JMXHelper().register(this);
}

public static NewSessionQueue create(Config config) {
Expand All @@ -80,6 +88,17 @@ public boolean isReady() {
return bus.isReady();
}

@ManagedAttribute(name = "NewSessionQueueSize")
public int getQueueSize() {
Lock readLock = lock.readLock();
readLock.lock();
try {
return sessionRequests.size();
} finally {
readLock.unlock();
}
}

@Override
public boolean offerLast(HttpRequest request, RequestId requestId) {
Require.nonNull("New Session request", request);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,7 @@ java_library(
srcs = glob(["*.java"]),
visibility = [
"//java/server/src/org/openqa/selenium/grid/session:__pkg__",
"//java/server/src/org/openqa/selenium/grid:__subpackages__",
"//java/server/test/org/openqa/selenium/grid:__subpackages__",
],
)
2 changes: 2 additions & 0 deletions java/server/test/org/openqa/selenium/grid/router/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,14 @@ java_test_suite(
"//java/server/src/org/openqa/selenium/grid/sessionmap/httpd",
"//java/server/src/org/openqa/selenium/grid/sessionmap/local",
"//java/server/src/org/openqa/selenium/grid/sessionmap/remote",
"//java/server/src/org/openqa/selenium/grid/sessionqueue/config",
"//java/server/src/org/openqa/selenium/grid/sessionqueue",
"//java/server/src/org/openqa/selenium/grid/sessionqueue/httpd",
"//java/server/src/org/openqa/selenium/grid/sessionqueue/local",
"//java/server/src/org/openqa/selenium/grid/sessionqueue/remote",
"//java/server/src/org/openqa/selenium/grid/web",
"//java/server/src/org/openqa/selenium/netty/server",
"//java/server/src/org/openqa/selenium/remote/server/jmx",
"//java/server/test/org/openqa/selenium/grid/testing",
artifact("com.google.guava:guava"),
artifact("io.opentelemetry:opentelemetry-api"),
Expand Down
Loading