Skip to content

Commit df4960b

Browse files
authored
Add jetty.yaml to JMX scraper (#1517)
1 parent e0fbc71 commit df4960b

File tree

9 files changed

+224
-36
lines changed

9 files changed

+224
-36
lines changed

jmx-metrics/src/integrationTest/java/io/opentelemetry/contrib/jmxmetrics/target_systems/JettyIntegrationTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ void endToEnd() throws InterruptedException {
5656
metric,
5757
"jetty.session.count",
5858
"The number of sessions established in total.",
59-
"{sessions}",
59+
"{session}",
6060
attrs -> attrs.containsKey("resource")),
6161
metric ->
6262
assertSumWithAttributes(
@@ -73,20 +73,20 @@ void endToEnd() throws InterruptedException {
7373
"s",
7474
attrs -> attrs.containsKey("resource")),
7575
metric ->
76-
assertSum(metric, "jetty.select.count", "The number of select calls.", "{operations}"),
76+
assertSum(metric, "jetty.select.count", "The number of select calls.", "{operation}"),
7777
metric ->
7878
assertGaugeWithAttributes(
7979
metric,
8080
"jetty.thread.count",
8181
"The current number of threads.",
82-
"{threads}",
82+
"{thread}",
8383
attrs -> attrs.contains(entry("state", "busy")),
8484
attrs -> attrs.contains(entry("state", "idle"))),
8585
metric ->
8686
assertGauge(
8787
metric,
8888
"jetty.thread.queue.count",
8989
"The current number of threads in the queue.",
90-
"{threads}"));
90+
"{thread}"));
9191
}
9292
}

jmx-metrics/src/main/resources/target-systems/jetty.groovy

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@
1515
*/
1616

1717
def beanSelector = otel.mbean("org.eclipse.jetty.io:context=*,type=managedselector,id=*")
18-
otel.instrument(beanSelector, "jetty.select.count", "The number of select calls.", "{operations}","selectCount", otel.&longCounterCallback)
18+
otel.instrument(beanSelector, "jetty.select.count", "The number of select calls.", "{operation}","selectCount", otel.&longCounterCallback)
1919

2020
def beanSessions = otel.mbean("org.eclipse.jetty.server.session:context=*,type=sessionhandler,id=*")
21-
otel.instrument(beanSessions, "jetty.session.count", "The number of sessions established in total.", "{sessions}",
21+
otel.instrument(beanSessions, "jetty.session.count", "The number of sessions established in total.", "{session}",
2222
["resource" : { mbean -> mbean.name().getKeyProperty("context") }],
2323
"sessionsCreated", otel.&longCounterCallback)
2424
otel.instrument(beanSessions, "jetty.session.time.total", "The total time sessions have been active.", "s",
@@ -29,9 +29,9 @@ otel.instrument(beanSessions, "jetty.session.time.max", "The maximum amount of t
2929
"sessionTimeMax", otel.&longValueCallback)
3030

3131
def beanThreads = otel.mbean("org.eclipse.jetty.util.thread:type=queuedthreadpool,id=*")
32-
otel.instrument(beanThreads, "jetty.thread.count", "The current number of threads.", "{threads}",
32+
otel.instrument(beanThreads, "jetty.thread.count", "The current number of threads.", "{thread}",
3333
[
3434
"busyThreads":["state" : {"busy"}],
3535
"idleThreads": ["state" : {"idle"}]
3636
], otel.&longValueCallback)
37-
otel.instrument(beanThreads, "jetty.thread.queue.count", "The current number of threads in the queue.", "{threads}","queueSize", otel.&longValueCallback)
37+
otel.instrument(beanThreads, "jetty.thread.queue.count", "The current number of threads in the queue.", "{thread}","queueSize", otel.&longValueCallback)

jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/ActiveMqIntegrationTest.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,7 @@ protected GenericContainer<?> createTargetContainer(int jmxPort) {
2323
new ImageFromDockerfile()
2424
.withDockerfileFromBuilder(
2525
builder -> builder.from("apache/activemq-classic:5.18.6").build()))
26-
.withEnv(
27-
"JAVA_TOOL_OPTIONS",
28-
"-Dcom.sun.management.jmxremote.port="
29-
+ jmxPort
30-
+ " -Dcom.sun.management.jmxremote.rmi.port="
31-
+ jmxPort
32-
+ " -Dcom.sun.management.jmxremote.ssl=false"
33-
+ " -Dcom.sun.management.jmxremote.authenticate=false")
26+
.withEnv("JAVA_TOOL_OPTIONS", genericJmxJvmArguments(jmxPort))
3427
.withStartupTimeout(Duration.ofMinutes(2))
3528
.waitingFor(Wait.forListeningPort());
3629
}

jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/CassandraIntegrationTest.java

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,24 +18,17 @@
1818
import org.assertj.core.api.MapAssert;
1919
import org.testcontainers.containers.GenericContainer;
2020
import org.testcontainers.containers.wait.strategy.Wait;
21-
import org.testcontainers.images.builder.ImageFromDockerfile;
2221

2322
public class CassandraIntegrationTest extends TargetSystemIntegrationTest {
2423

2524
@Override
2625
protected GenericContainer<?> createTargetContainer(int jmxPort) {
27-
return new GenericContainer<>(
28-
new ImageFromDockerfile()
29-
.withDockerfileFromBuilder(builder -> builder.from("cassandra:5.0.2").build()))
26+
return new GenericContainer<>("cassandra:5.0.2")
3027
.withEnv(
3128
"JVM_EXTRA_OPTS",
32-
" -Dcassandra.jmx.remote.port="
33-
+ jmxPort
34-
+ " -Dcom.sun.management.jmxremote.rmi.port="
35-
+ jmxPort
36-
+ " -Dcom.sun.management.jmxremote.local.only=false"
37-
+ " -Dcom.sun.management.jmxremote.ssl=false"
38-
+ " -Dcom.sun.management.jmxremote.authenticate=false")
29+
genericJmxJvmArguments(jmxPort)
30+
// making cassandra startup faster for single node, from ~1min to ~15s
31+
+ " -Dcassandra.skip_wait_for_gossip_to_settle=0 -Dcassandra.initial_token=0")
3932
.withStartupTimeout(Duration.ofMinutes(2))
4033
.waitingFor(Wait.forLogMessage(".*Startup complete.*", 1));
4134
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.contrib.jmxscraper.target_systems;
7+
8+
import static io.opentelemetry.contrib.jmxscraper.target_systems.MetricAssertions.assertGauge;
9+
import static io.opentelemetry.contrib.jmxscraper.target_systems.MetricAssertions.assertGaugeWithAttributes;
10+
import static io.opentelemetry.contrib.jmxscraper.target_systems.MetricAssertions.assertSumWithAttributes;
11+
import static io.opentelemetry.contrib.jmxscraper.target_systems.MetricAssertions.assertSumWithAttributesMultiplePoints;
12+
13+
import io.opentelemetry.contrib.jmxscraper.JmxScraperContainer;
14+
import java.time.Duration;
15+
import org.testcontainers.containers.GenericContainer;
16+
import org.testcontainers.containers.wait.strategy.Wait;
17+
import org.testcontainers.images.builder.ImageFromDockerfile;
18+
19+
public class JettyIntegrationTest extends TargetSystemIntegrationTest {
20+
21+
@Override
22+
protected GenericContainer<?> createTargetContainer(int jmxPort) {
23+
GenericContainer<?> container =
24+
new GenericContainer<>(
25+
new ImageFromDockerfile()
26+
.withDockerfileFromBuilder(
27+
builder ->
28+
builder
29+
.from("jetty:11")
30+
.run(
31+
"java",
32+
"-jar",
33+
"/usr/local/jetty/start.jar",
34+
"--add-to-startd=jmx,stats,http")
35+
.run("mkdir -p /var/lib/jetty/webapps/ROOT/")
36+
.run("touch /var/lib/jetty/webapps/ROOT/index.html")
37+
.build()));
38+
39+
container
40+
.withEnv("JAVA_OPTIONS", genericJmxJvmArguments(jmxPort))
41+
.withStartupTimeout(Duration.ofMinutes(2))
42+
.waitingFor(Wait.forLogMessage(".*Started Server.*", 1));
43+
44+
return container;
45+
}
46+
47+
@Override
48+
protected JmxScraperContainer customizeScraperContainer(JmxScraperContainer scraper) {
49+
return scraper.withTargetSystem("jetty");
50+
}
51+
52+
@Override
53+
protected void verifyMetrics() {
54+
waitAndAssertMetrics(
55+
metric ->
56+
assertSumWithAttributes(
57+
metric,
58+
"jetty.session.count",
59+
"The number of sessions established in total.",
60+
"{session}",
61+
attrs -> attrs.containsKey("resource")),
62+
metric ->
63+
assertSumWithAttributes(
64+
metric,
65+
"jetty.session.time.total",
66+
"The total time sessions have been active.",
67+
"s",
68+
attrs -> attrs.containsKey("resource")),
69+
metric ->
70+
assertGaugeWithAttributes(
71+
metric,
72+
"jetty.session.time.max",
73+
"The maximum amount of time a session has been active.",
74+
"s",
75+
attrs -> attrs.containsKey("resource")),
76+
metric ->
77+
assertSumWithAttributesMultiplePoints(
78+
metric,
79+
"jetty.select.count",
80+
"The number of select calls.",
81+
"{operation}",
82+
/* isMonotonic= */ true,
83+
// minor divergence from jetty.groovy with extra metrics attributes
84+
attrs -> attrs.containsKey("context").containsKey("id")),
85+
metric ->
86+
assertGaugeWithAttributes(
87+
metric,
88+
"jetty.thread.count",
89+
"The current number of threads.",
90+
"{thread}",
91+
attrs -> attrs.containsEntry("state", "busy"),
92+
attrs -> attrs.containsEntry("state", "idle")),
93+
metric ->
94+
assertGauge(
95+
metric,
96+
"jetty.thread.queue.count",
97+
"The current number of threads in the queue.",
98+
"{thread}"));
99+
}
100+
}

jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/MetricAssertions.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,22 @@ static void assertSumWithAttributes(
9292
assertAttributedPoints(metric.getSum().getDataPointsList(), attributeGroupAssertions);
9393
}
9494

95+
@SafeVarargs
96+
static void assertSumWithAttributesMultiplePoints(
97+
Metric metric,
98+
String name,
99+
String description,
100+
String unit,
101+
boolean isMonotonic,
102+
Consumer<MapAssert<String, String>>... attributeGroupAssertions) {
103+
assertThat(metric.getName()).isEqualTo(name);
104+
assertThat(metric.getDescription()).isEqualTo(description);
105+
assertThat(metric.getUnit()).isEqualTo(unit);
106+
assertThat(metric.hasSum()).isTrue();
107+
assertThat(metric.getSum().getIsMonotonic()).isEqualTo(isMonotonic);
108+
assertAttributedMultiplePoints(metric.getSum().getDataPointsList(), attributeGroupAssertions);
109+
}
110+
95111
@SafeVarargs
96112
static void assertGaugeWithAttributes(
97113
Metric metric,
@@ -127,6 +143,7 @@ private static void assertAttributedPoints(
127143
Arrays.stream(attributeGroupAssertions)
128144
.map(assertion -> (Consumer<Map<String, String>>) m -> assertion.accept(assertThat(m)))
129145
.toArray(Consumer[]::new);
146+
130147
assertThat(points)
131148
.extracting(
132149
numberDataPoint ->
@@ -136,4 +153,22 @@ private static void assertAttributedPoints(
136153
KeyValue::getKey, keyValue -> keyValue.getValue().getStringValue())))
137154
.satisfiesExactlyInAnyOrder(assertions);
138155
}
156+
157+
@SuppressWarnings("unchecked")
158+
private static void assertAttributedMultiplePoints(
159+
List<NumberDataPoint> points,
160+
Consumer<MapAssert<String, String>>... attributeGroupAssertions) {
161+
162+
points.stream()
163+
.map(NumberDataPoint::getAttributesList)
164+
.forEach(
165+
kvList -> {
166+
Map<String, String> kvMap =
167+
kvList.stream()
168+
.collect(
169+
Collectors.toMap(KeyValue::getKey, kv -> kv.getValue().getStringValue()));
170+
Arrays.stream(attributeGroupAssertions)
171+
.forEach(assertion -> assertion.accept(assertThat(kvMap)));
172+
});
173+
}
139174
}

jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/TargetSystemIntegrationTest.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,4 +196,14 @@ public void export(
196196
sb.http(0);
197197
}
198198
}
199+
200+
protected static String genericJmxJvmArguments(int port) {
201+
return "-Dcom.sun.management.jmxremote.local.only=false"
202+
+ " -Dcom.sun.management.jmxremote.authenticate=false"
203+
+ " -Dcom.sun.management.jmxremote.ssl=false"
204+
+ " -Dcom.sun.management.jmxremote.port="
205+
+ port
206+
+ " -Dcom.sun.management.jmxremote.rmi.port="
207+
+ port;
208+
}
199209
}

jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/TomcatIntegrationTest.java

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,7 @@ protected GenericContainer<?> createTargetContainer(int jmxPort) {
3030
"https://tomcat.apache.org/tomcat-9.0-doc/appdev/sample/sample.war",
3131
"/usr/local/tomcat/webapps/ROOT.war")
3232
.build()))
33-
.withEnv(
34-
"CATALINA_OPTS",
35-
"-Dcom.sun.management.jmxremote.local.only=false"
36-
+ " -Dcom.sun.management.jmxremote.authenticate=false"
37-
+ " -Dcom.sun.management.jmxremote.ssl=false"
38-
+ " -Dcom.sun.management.jmxremote.port="
39-
+ jmxPort
40-
+ " -Dcom.sun.management.jmxremote.rmi.port="
41-
+ jmxPort)
33+
.withEnv("CATALINA_OPTS", genericJmxJvmArguments(jmxPort))
4234
.withStartupTimeout(Duration.ofMinutes(2))
4335
.waitingFor(Wait.forListeningPort());
4436
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
---
2+
3+
rules:
4+
5+
- bean: org.eclipse.jetty.io:context=*,type=managedselector,id=*
6+
mapping:
7+
selectCount:
8+
metric: jetty.select.count
9+
type: counter
10+
unit: "{operation}"
11+
desc: The number of select calls.
12+
metricAttribute:
13+
# minor divergence from jetty.groovy with extra attribute(s)
14+
# 'id' is a numerical value in [0,9] by default
15+
# 'context' is a high cardinality value like 'HTTP_1_1@7674f035' but likely stable for the
16+
# duration of the jetty process lifecycle
17+
context: param(context)
18+
id: param(id)
19+
20+
- bean: org.eclipse.jetty.server.session:context=*,type=sessionhandler,id=*
21+
prefix: jetty.session.
22+
metricAttribute:
23+
resource: param(context)
24+
mapping:
25+
sessionsCreated:
26+
metric: count
27+
type: counter
28+
unit: "{session}"
29+
desc: The number of sessions established in total.
30+
sessionTimeTotal:
31+
metric: time.total
32+
type: counter
33+
unit: s
34+
desc: The total time sessions have been active.
35+
sessionTimeMax:
36+
metric: time.max
37+
# here a 'counter' seems more appropriate but gauge reflects jetty.groovy impl.
38+
type: gauge
39+
unit: s
40+
desc: The maximum amount of time a session has been active.
41+
42+
- bean: org.eclipse.jetty.util.thread:type=queuedthreadpool,id=*
43+
# here the 'id' can be ignored as it's usually a single value equal to '0'
44+
prefix: jetty.thread.
45+
unit: "{thread}"
46+
mapping:
47+
busyThreads:
48+
metric: count
49+
# here an 'updowncounter' seems more appropriate but gauge reflects jetty.groovy impl.
50+
type: gauge
51+
desc: The current number of threads.
52+
metricAttribute:
53+
state: const(busy)
54+
idleThreads:
55+
metric: count
56+
# here an 'updowncounter' seems more appropriate but gauge reflects jetty.groovy impl.
57+
type: gauge
58+
desc: The current number of threads.
59+
metricAttribute:
60+
state: const(idle)
61+
queueSize:
62+
metric: queue.count
63+
# here an 'updowncounter' seems more appropriate but gauge reflects jetty.groovy impl.
64+
type: gauge
65+
desc: The current number of threads in the queue.

0 commit comments

Comments
 (0)