Skip to content

Commit e4547d4

Browse files
authored
enhance & align jetty jmx metrics (#14067)
1 parent 4c4b7e2 commit e4547d4

File tree

8 files changed

+285
-79
lines changed

8 files changed

+285
-79
lines changed

instrumentation/jmx-metrics/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ No targets are enabled by default. The supported target environments are listed
2727

2828
- [activemq](javaagent/activemq.md)
2929
- [camel](javaagent/camel.md)
30-
- [jetty](javaagent/jetty.md)
30+
- [jetty](library/jetty.md)
3131
- [kafka-broker](javaagent/kafka-broker.md)
3232
- [tomcat](library/tomcat.md)
3333
- [wildfly](javaagent/wildfly.md)

instrumentation/jmx-metrics/javaagent/jetty.md

Lines changed: 0 additions & 16 deletions
This file was deleted.

instrumentation/jmx-metrics/javaagent/src/main/resources/jmx/rules/jetty.yaml

Lines changed: 0 additions & 55 deletions
This file was deleted.

instrumentation/jmx-metrics/javaagent/src/test/java/io/opentelemetry/instrumentation/javaagent/jmx/JmxMetricInsightInstallerTest.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,7 @@ class JmxMetricInsightInstallerTest {
3333
private static final Set<String> FILES_TO_BE_TESTED =
3434
new HashSet<>(
3535
Arrays.asList(
36-
"activemq.yaml",
37-
"camel.yaml",
38-
"hadoop.yaml",
39-
"jetty.yaml",
40-
"kafka-broker.yaml",
41-
"wildfly.yaml"));
36+
"activemq.yaml", "camel.yaml", "hadoop.yaml", "kafka-broker.yaml", "wildfly.yaml"));
4237

4338
@Test
4439
void testToVerifyExistingRulesAreValid() throws Exception {
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Jetty Metrics
2+
3+
Here is the list of metrics based on MBeans exposed by [Jetty](https://jetty.org/).
4+
5+
The metrics captured and their respective attributes depend on the Jetty version:
6+
- [Jetty 12 and later](#jetty-12-and-later)
7+
- [Jetty 9 to 11](#jetty-9-to-11)
8+
9+
## Jetty 12 and later
10+
11+
Those metrics require the following Jetty modules to be enabled : `jmx`, `http`, `statistics`, `sessions` and at least one of `ee8-deploy`, `ee9-deploy` or `ee10-deploy`.
12+
13+
| Metric Name | Type | Attributes | Description |
14+
|-------------------------|---------------|---------------|-------------------------------------------|
15+
| jetty.thread.count | UpDownCounter | | The current number of threads |
16+
| jetty.thread.limit | UpDownCounter | | The maximum number of threads in the pool |
17+
| jetty.thread.busy.count | UpDownCounter | | The current number of busy threads |
18+
| jetty.thread.idle.count | UpDownCounter | | The current number of idle threads |
19+
| jetty.thread.queue.size | UpDownCounter | | The current job queue size |
20+
| jetty.io.select.count | Counter | | The number of select calls |
21+
| jetty.session.count | UpDownCounter | jetty.context | Current number of active sessions |
22+
23+
- `jetty.context` corresponds to the deployed application subfolder in `webapps` folder.
24+
25+
## Jetty 9 to 11
26+
27+
Those metrics require the following Jetty modules to be enabled : `jmx`, `http` and `stats`.
28+
29+
| Metric Name | Type | Attributes | Description |
30+
|-----------------------------|---------------|---------------|-------------------------------------------|
31+
| jetty.thread.count | UpDownCounter | | The current number of threads |
32+
| jetty.thread.limit | UpDownCounter | | The maximum number of threads in the pool |
33+
| jetty.thread.busy.count | UpDownCounter | | The current number of busy threads |
34+
| jetty.thread.idle.count | UpDownCounter | | The current number of idle threads |
35+
| jetty.thread.queue.size | UpDownCounter | | The current job queue size |
36+
| jetty.io.select.count | Counter | | The number of select calls |
37+
| jetty.session.created.count | Counter | jetty.context | The total number of created sessions |
38+
| jetty.session.duration.sum | Counter | jetty.context | The cumulated session duration |
39+
40+
- `jetty.context` corresponds to the deployed application subfolder in `webapps` folder.
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
---
2+
rules:
3+
4+
# Thread metrics
5+
- beans:
6+
# Jetty 12 and later
7+
- org.eclipse.jetty.util.thread:context=*,type=queuedthreadpool,id=*
8+
# Jetty 9 to 11
9+
- org.eclipse.jetty.util.thread:type=queuedthreadpool,id=*
10+
# usually a single mbean instance exists, thus the metric is aggregated (sum for updowncounter)
11+
prefix: jetty.thread.
12+
unit: "{thread}"
13+
type: updowncounter
14+
mapping:
15+
# jetty.thread.count
16+
threads:
17+
metric: count
18+
desc: The current number of threads
19+
# jetty.thread.limit
20+
maxThreads:
21+
metric: limit
22+
desc: The configured maximum number of threads in the pool
23+
# jetty.thread.idle.count
24+
idleThreads:
25+
metric: idle.count
26+
desc: The current number of idle threads
27+
# jetty.thread.busy.count
28+
busyThreads:
29+
metric: busy.count
30+
desc: The current number of busy threads
31+
# jetty.thread.queue.size
32+
queueSize:
33+
metric: queue.size
34+
desc: The current job queue size
35+
36+
- bean: org.eclipse.jetty.io:context=*,type=managedselector,id=*
37+
mapping:
38+
# jetty.select.count
39+
selectCount:
40+
metric: jetty.select.count
41+
type: counter
42+
unit: "{operation}"
43+
desc: The number of select calls
44+
45+
# Session metrics for Jetty 12
46+
- bean: org.eclipse.jetty.session:context=*,type=defaultsessioncache,id=*
47+
# Usually a single mbean instance exists per context, thus the metric is aggregated: sum for counter,
48+
# gauge metrics will return invalid (last-value) with more than 1 mbean instance, thus none
49+
# is included in this provided configuration.
50+
prefix: jetty.session.
51+
unit: "{session}"
52+
metricAttribute:
53+
# 'context' corresponds to the webapp context path
54+
jetty.context: param(context)
55+
mapping:
56+
# jetty.session.count
57+
sessionsCurrent:
58+
metric: count
59+
type: updowncounter
60+
desc: Current number of active sessions
61+
62+
# Session metrics for Jetty 9 to 11
63+
- bean: org.eclipse.jetty.server.session:context=*,type=sessionhandler,id=*
64+
# Usually a single mbean instance exists per context, thus the metric is aggregated: sum for counter,
65+
# gauge metrics will return invalid (last-value) with more than 1 mbean instance, thus none
66+
# is included in this provided configuration.
67+
prefix: jetty.session.
68+
metricAttribute:
69+
# 'context' corresponds to the webapp context path
70+
jetty.context: param(context)
71+
mapping:
72+
# jetty.session.created.count
73+
sessionsCreated:
74+
metric: created.count
75+
unit: "{session}"
76+
type: counter
77+
desc: The total number of created sessions
78+
# jetty.session.duration.sum
79+
sessionTimeTotal:
80+
metric: duration.sum
81+
unit: s
82+
type: counter
83+
desc: The cumulated session duration
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.instrumentation.jmx.rules;
7+
8+
import static io.opentelemetry.instrumentation.jmx.rules.assertions.DataPointAttributes.attributeWithAnyValue;
9+
10+
import io.opentelemetry.instrumentation.jmx.rules.assertions.AttributeMatcher;
11+
import java.time.Duration;
12+
import java.util.ArrayList;
13+
import java.util.Arrays;
14+
import java.util.Collections;
15+
import java.util.HashSet;
16+
import java.util.List;
17+
import java.util.Set;
18+
import org.junit.jupiter.params.ParameterizedTest;
19+
import org.junit.jupiter.params.provider.ValueSource;
20+
import org.testcontainers.containers.GenericContainer;
21+
import org.testcontainers.containers.wait.strategy.Wait;
22+
import org.testcontainers.images.builder.ImageFromDockerfile;
23+
24+
public class JettyIntegrationTest extends TargetSystemTest {
25+
26+
private static final int JETTY_PORT = 8080;
27+
28+
@ParameterizedTest(name = "jetty:{arguments}")
29+
@ValueSource(ints = {9, 10, 11, 12})
30+
void testCollectedMetrics(int jettyMajorVersion) {
31+
32+
List<String> yamlFiles = Collections.singletonList("jetty.yaml");
33+
34+
yamlFiles.forEach(this::validateYamlSyntax);
35+
36+
List<String> jvmArgs = new ArrayList<>();
37+
jvmArgs.add(javaAgentJvmArgument());
38+
jvmArgs.addAll(javaPropertiesToJvmArgs(otelConfigProperties(yamlFiles)));
39+
40+
Set<String> jettyModules = new HashSet<>(Arrays.asList("jmx", "http"));
41+
if (jettyMajorVersion >= 12) {
42+
jettyModules.add("statistics");
43+
// required for session management
44+
jettyModules.add("sessions");
45+
// required for deployment support in 'webapps' folder
46+
jettyModules.add("ee10-deploy");
47+
} else {
48+
// with older versions deployment and session management are available by default
49+
jettyModules.add("stats");
50+
}
51+
String addModulesArg = "--add-to-startd=" + String.join(",", jettyModules);
52+
53+
GenericContainer<?> container =
54+
new GenericContainer<>(
55+
new ImageFromDockerfile()
56+
.withDockerfileFromBuilder(
57+
builder ->
58+
builder
59+
.from("jetty:" + jettyMajorVersion)
60+
.run("java", "-jar", "/usr/local/jetty/start.jar", addModulesArg)
61+
.run("mkdir -p /var/lib/jetty/webapps/ROOT/")
62+
.run("touch /var/lib/jetty/webapps/ROOT/index.html")
63+
.build()))
64+
.withEnv("JAVA_OPTIONS", String.join(" ", jvmArgs))
65+
.withStartupTimeout(Duration.ofMinutes(2))
66+
.withExposedPorts(JETTY_PORT)
67+
.waitingFor(Wait.forListeningPorts(JETTY_PORT));
68+
69+
copyFilesToTarget(container, yamlFiles);
70+
71+
startTarget(container);
72+
73+
verifyMetrics(createMetricsVerifier(jettyMajorVersion));
74+
}
75+
76+
private static MetricsVerifier createMetricsVerifier(int jettyMajorVersion) {
77+
78+
MetricsVerifier verifier =
79+
MetricsVerifier.create()
80+
.add(
81+
"jetty.thread.count",
82+
metric ->
83+
metric
84+
.isUpDownCounter()
85+
.hasDescription("The current number of threads")
86+
.hasUnit("{thread}")
87+
.hasDataPointsWithoutAttributes())
88+
.add(
89+
"jetty.thread.limit",
90+
metric ->
91+
metric
92+
.isUpDownCounter()
93+
.hasDescription("The configured maximum number of threads in the pool")
94+
.hasUnit("{thread}")
95+
.hasDataPointsWithoutAttributes())
96+
.add(
97+
"jetty.thread.idle.count",
98+
metric ->
99+
metric
100+
.isUpDownCounter()
101+
.hasDescription("The current number of idle threads")
102+
.hasUnit("{thread}")
103+
.hasDataPointsWithoutAttributes())
104+
.add(
105+
"jetty.thread.busy.count",
106+
metric ->
107+
metric
108+
.isUpDownCounter()
109+
.hasDescription("The current number of busy threads")
110+
.hasUnit("{thread}")
111+
.hasDataPointsWithoutAttributes())
112+
.add(
113+
"jetty.thread.queue.size",
114+
metric ->
115+
metric
116+
.isUpDownCounter()
117+
.hasDescription("The current job queue size")
118+
.hasUnit("{thread}")
119+
.hasDataPointsWithoutAttributes())
120+
.add(
121+
"jetty.select.count",
122+
metric ->
123+
metric
124+
.isCounter()
125+
.hasDescription("The number of select calls")
126+
.hasUnit("{operation}")
127+
.hasDataPointsWithoutAttributes());
128+
129+
AttributeMatcher contextAttribute = attributeWithAnyValue("jetty.context");
130+
if (jettyMajorVersion >= 12) {
131+
verifier.add(
132+
"jetty.session.count",
133+
metric ->
134+
metric
135+
.isUpDownCounter()
136+
.hasDescription("Current number of active sessions")
137+
.hasUnit("{session}")
138+
.hasDataPointsWithOneAttribute(contextAttribute));
139+
} else {
140+
verifier
141+
.add(
142+
"jetty.session.created.count",
143+
metric ->
144+
metric
145+
.isCounter()
146+
.hasDescription("The total number of created sessions")
147+
.hasUnit("{session}")
148+
.hasDataPointsWithOneAttribute(contextAttribute))
149+
.add(
150+
"jetty.session.duration.sum",
151+
metric ->
152+
metric
153+
.isCounter()
154+
.hasDescription("The cumulated session duration")
155+
.hasUnit("s")
156+
.hasDataPointsWithOneAttribute(contextAttribute));
157+
}
158+
return verifier;
159+
}
160+
}

instrumentation/jmx-metrics/library/src/test/java/io/opentelemetry/instrumentation/jmx/rules/TomcatIntegrationTest.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ void testCollectedMetrics(String dockerImageName, String sampleWebApplicationUrl
3636
jvmArgs.add(javaAgentJvmArgument());
3737
jvmArgs.addAll(javaPropertiesToJvmArgs(otelConfigProperties(yamlFiles)));
3838

39-
// testing with a basic tomcat image as test application to capture JVM metrics
4039
GenericContainer<?> target =
4140
new GenericContainer<>(dockerImageName)
4241
.withEnv("CATALINA_OPTS", String.join(" ", jvmArgs))

0 commit comments

Comments
 (0)