Skip to content

Commit 891e043

Browse files
committed
Expose server config, session queue and node as MBeans for JMX monitoring.
1 parent 474d116 commit 891e043

File tree

12 files changed

+317
-0
lines changed

12 files changed

+317
-0
lines changed

java/server/src/org/openqa/selenium/grid/node/BUILD.bazel

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ java_library(
2121
"//java/server/src/org/openqa/selenium/grid/security",
2222
"//java/server/src/org/openqa/selenium/grid/web",
2323
"//java/server/src/org/openqa/selenium/status",
24+
"//java/server/src/org/openqa/selenium/remote/server/jmx",
2425
artifact("com.google.guava:guava"),
2526
],
2627
)

java/server/src/org/openqa/selenium/grid/node/local/BUILD.bazel

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ java_library(
2525
"//java/server/src/org/openqa/selenium/grid/node/config",
2626
"//java/server/src/org/openqa/selenium/grid/security",
2727
"//java/server/src/org/openqa/selenium/grid/server",
28+
"//java/server/src/org/openqa/selenium/remote/server/jmx",
2829
artifact("com.google.guava:guava"),
2930
],
3031
)

java/server/src/org/openqa/selenium/grid/node/local/LocalNode.java

+50
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.openqa.selenium.WebDriverException;
3232
import org.openqa.selenium.concurrent.Regularly;
3333
import org.openqa.selenium.events.EventBus;
34+
import org.openqa.selenium.grid.data.Availability;
3435
import org.openqa.selenium.grid.data.CreateSessionRequest;
3536
import org.openqa.selenium.grid.data.CreateSessionResponse;
3637
import org.openqa.selenium.grid.data.NodeDrainComplete;
@@ -53,6 +54,9 @@
5354
import org.openqa.selenium.remote.SessionId;
5455
import org.openqa.selenium.remote.http.HttpRequest;
5556
import org.openqa.selenium.remote.http.HttpResponse;
57+
import org.openqa.selenium.remote.server.jmx.JMXHelper;
58+
import org.openqa.selenium.remote.server.jmx.ManagedAttribute;
59+
import org.openqa.selenium.remote.server.jmx.ManagedService;
5660
import org.openqa.selenium.remote.tracing.AttributeKey;
5761
import org.openqa.selenium.remote.tracing.EventAttribute;
5862
import org.openqa.selenium.remote.tracing.EventAttributeValue;
@@ -91,6 +95,8 @@
9195
import static org.openqa.selenium.remote.http.Contents.string;
9296
import static org.openqa.selenium.remote.http.HttpMethod.DELETE;
9397

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

96102
private static final Json JSON = new Json();
@@ -174,6 +180,8 @@ private LocalNode(
174180
}
175181
}
176182
}));
183+
184+
new JMXHelper().register(this);
177185
}
178186

179187
@Override
@@ -182,11 +190,53 @@ public boolean isReady() {
182190
}
183191

184192
@VisibleForTesting
193+
@ManagedAttribute(name = "CurrentSessions")
185194
public int getCurrentSessionCount() {
186195
// It seems wildly unlikely we'll overflow an int
187196
return Math.toIntExact(currentSessions.size());
188197
}
189198

199+
@ManagedAttribute(name = "MaxSessions")
200+
public int getMaxSessionCount() {
201+
return maxSessionCount;
202+
}
203+
204+
@ManagedAttribute(name = "Status")
205+
public Availability getAvailability() {
206+
return isDraining() ? DRAINING : UP;
207+
}
208+
209+
@ManagedAttribute(name = "TotalSlots")
210+
public int getTotalSlots() {
211+
return factories.size();
212+
}
213+
214+
@ManagedAttribute(name = "UsedSlots")
215+
public long getUsedSlots() {
216+
return factories.stream().filter(sessionSlot -> !sessionSlot.isAvailable()).count();
217+
}
218+
219+
@ManagedAttribute(name = "Load")
220+
public float getLoad() {
221+
long inUse = factories.stream().filter(sessionSlot -> !sessionSlot.isAvailable()).count();
222+
return inUse / (float) maxSessionCount * 100f;
223+
}
224+
225+
@ManagedAttribute(name = "RemoteNodeUri")
226+
public URI getExternalURI() {
227+
return externalUri;
228+
}
229+
230+
@ManagedAttribute(name = "GridUri")
231+
public URI getGridURI() {
232+
return gridUri;
233+
}
234+
235+
@ManagedAttribute(name = "NodeId")
236+
public String getNodeId() {
237+
return getId().toString();
238+
}
239+
190240
@Override
191241
public boolean isSupporting(Capabilities capabilities) {
192242
return factories.parallelStream().anyMatch(factory -> factory.test(capabilities));

java/server/src/org/openqa/selenium/grid/server/BUILD.bazel

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ java_library(
2020
"//java/server/src/org/openqa/selenium/grid/component",
2121
"//java/server/src/org/openqa/selenium/grid/config",
2222
"//java/server/src/org/openqa/selenium/grid/web",
23+
"//java/server/src/org/openqa/selenium/remote/server/jmx",
2324
artifact("com.beust:jcommander"),
2425
artifact("com.google.guava:guava"),
2526
artifact("javax.servlet:javax.servlet-api"),

java/server/src/org/openqa/selenium/grid/server/BaseServerOptions.java

+19
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,20 @@
2323
import org.openqa.selenium.net.HostIdentifier;
2424
import org.openqa.selenium.net.NetworkUtils;
2525
import org.openqa.selenium.net.PortProber;
26+
import org.openqa.selenium.remote.server.jmx.JMXHelper;
27+
import org.openqa.selenium.remote.server.jmx.ManagedAttribute;
28+
import org.openqa.selenium.remote.server.jmx.ManagedService;
2629

2730
import java.io.File;
31+
import java.net.MalformedURLException;
2832
import java.net.URI;
2933
import java.net.URISyntaxException;
34+
import java.net.URL;
3035
import java.util.Optional;
3136
import java.util.logging.Logger;
3237

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

3542
private static final String SERVER_SECTION = "server";
@@ -40,12 +47,14 @@ public class BaseServerOptions {
4047

4148
public BaseServerOptions(Config config) {
4249
this.config = config;
50+
new JMXHelper().register(this);
4351
}
4452

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

57+
@ManagedAttribute(name = "Port")
4958
public int getPort() {
5059
if (port == -1) {
5160
int newPort = config.getInt(SERVER_SECTION, "port")
@@ -61,6 +70,7 @@ public int getPort() {
6170
return port;
6271
}
6372

73+
@ManagedAttribute(name = "MaxServerThreads")
6474
public int getMaxServerThreads() {
6575
int count = config.getInt(SERVER_SECTION, "max-threads")
6676
.orElse(200);
@@ -94,6 +104,15 @@ public URI getExternalUri() {
94104
}
95105
}
96106

107+
@ManagedAttribute(name = "URL")
108+
public URL getExternalUrl() {
109+
try {
110+
return getExternalUri().toURL();
111+
} catch (MalformedURLException e) {
112+
throw new ConfigException("Cannot convert URI to URL" + e.getMessage());
113+
}
114+
}
115+
97116
public boolean getAllowCORS() {
98117
return config.getBool(SERVER_SECTION, "allow-cors").orElse(false);
99118
}

java/server/src/org/openqa/selenium/grid/sessionqueue/BUILD.bazel

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ java_library(
2020
"//java/server/src/org/openqa/selenium/grid/data",
2121
"//java/server/src/org/openqa/selenium/grid/log",
2222
"//java/server/src/org/openqa/selenium/status",
23+
"//java/server/src/org/openqa/selenium/remote/server/jmx",
2324
artifact("com.google.guava:guava"),
2425
],
2526
)

java/server/src/org/openqa/selenium/grid/sessionqueue/config/BUILD.bazel

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ java_library(
1111
"//java:auto-service",
1212
"//java/server/src/org/openqa/selenium/grid/config",
1313
"//java/server/src/org/openqa/selenium/grid/sessionqueue",
14+
"//java/server/src/org/openqa/selenium/remote/server/jmx",
1415
artifact("com.beust:jcommander"),
1516
artifact("io.opentelemetry:opentelemetry-api"),
1617
],

java/server/src/org/openqa/selenium/grid/sessionqueue/config/NewSessionQueueOptions.java

+17
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,15 @@
1919

2020
import org.openqa.selenium.grid.config.Config;
2121
import org.openqa.selenium.grid.sessionqueue.NewSessionQueue;
22+
import org.openqa.selenium.remote.server.jmx.JMXHelper;
23+
import org.openqa.selenium.remote.server.jmx.ManagedAttribute;
24+
import org.openqa.selenium.remote.server.jmx.ManagedService;
2225

2326
import java.time.Duration;
27+
import java.time.temporal.ChronoUnit;
2428

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

2733
private static final String SESSIONS_QUEUE_SECTION = "sessionqueue";
@@ -35,6 +41,7 @@ public class NewSessionQueueOptions {
3541

3642
public NewSessionQueueOptions(Config config) {
3743
this.config = config;
44+
new JMXHelper().register(this);
3845
}
3946

4047
public Duration getSessionRequestTimeout() {
@@ -57,6 +64,16 @@ public Duration getSessionRequestRetryInterval() {
5764
return Duration.ofSeconds(interval);
5865
}
5966

67+
@ManagedAttribute(name = "RequestTimeoutSeconds")
68+
public long getRequestTimeoutSeconds() {
69+
return getSessionRequestTimeout().get(ChronoUnit.SECONDS);
70+
}
71+
72+
@ManagedAttribute(name = "RetryIntervalSeconds")
73+
public long getRetryIntervalSeconds() {
74+
return getSessionRequestRetryInterval().get(ChronoUnit.SECONDS);
75+
}
76+
6077
public NewSessionQueue getSessionQueue() {
6178
return config
6279
.getClass(SESSIONS_QUEUE_SECTION, "implementation", NewSessionQueue.class,

java/server/src/org/openqa/selenium/grid/sessionqueue/local/BUILD.bazel

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ java_library(
1818
"//java/server/src/org/openqa/selenium/grid/server",
1919
"//java/server/src/org/openqa/selenium/grid/sessionqueue",
2020
"//java/server/src/org/openqa/selenium/grid/sessionqueue/config",
21+
"//java/server/src/org/openqa/selenium/remote/server/jmx",
2122
artifact("com.google.guava:guava"),
2223
],
2324
)

java/server/src/org/openqa/selenium/grid/sessionqueue/local/LocalNewSessionQueue.java

+17
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@
3030
import org.openqa.selenium.internal.Require;
3131
import org.openqa.selenium.remote.http.HttpRequest;
3232
import org.openqa.selenium.remote.http.HttpResponse;
33+
import org.openqa.selenium.remote.server.jmx.JMXHelper;
34+
import org.openqa.selenium.remote.server.jmx.ManagedAttribute;
35+
import org.openqa.selenium.remote.server.jmx.ManagedService;
3336
import org.openqa.selenium.remote.tracing.AttributeKey;
3437
import org.openqa.selenium.remote.tracing.EventAttribute;
3538
import org.openqa.selenium.remote.tracing.EventAttributeValue;
@@ -52,6 +55,8 @@
5255
import java.util.logging.Level;
5356
import java.util.logging.Logger;
5457

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

5762
private static final Logger LOG = Logger.getLogger(LocalNewSessionQueue.class.getName());
@@ -67,6 +72,7 @@ public LocalNewSessionQueue(Tracer tracer, EventBus bus, Duration retryInterval,
6772
super(tracer, retryInterval, requestTimeout);
6873
this.bus = Require.nonNull("Event bus", bus);
6974
Runtime.getRuntime().addShutdownHook(shutdownHook);
75+
new JMXHelper().register(this);
7076
}
7177

7278
public static NewSessionQueue create(Config config) {
@@ -82,6 +88,17 @@ public boolean isReady() {
8288
return bus.isReady();
8389
}
8490

91+
@ManagedAttribute(name = "NewSessionQueueSize")
92+
public int getQueueSize() {
93+
Lock writeLock = lock.writeLock();
94+
writeLock.lock();
95+
try {
96+
return sessionRequests.size();
97+
} finally {
98+
writeLock.unlock();
99+
}
100+
}
101+
85102
@Override
86103
public boolean offerLast(HttpRequest request, RequestId requestId) {
87104
Require.nonNull("New Session request", request);

java/server/src/org/openqa/selenium/remote/server/jmx/BUILD.bazel

+1
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ java_library(
55
srcs = glob(["*.java"]),
66
visibility = [
77
"//java/server/src/org/openqa/selenium/grid/session:__pkg__",
8+
"//java/server/src/org/openqa/selenium/grid:__subpackages__",
89
],
910
)

0 commit comments

Comments
 (0)