Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
f2cfd9d
move jetty definition to library
SylvainJuge May 27, 2025
408d948
Merge branch 'main' of github.com:open-telemetry/opentelemetry-java-i…
SylvainJuge Jun 16, 2025
cb29b8f
add jetty integration test
SylvainJuge Jun 17, 2025
380272e
add jetty thread metrics
SylvainJuge Jun 17, 2025
7d033ed
try to add jetty 12
SylvainJuge Jun 18, 2025
48d37a9
limit test to jetty 11
SylvainJuge Jun 18, 2025
a08ce78
test multiple jetty versions + doc
SylvainJuge Jun 18, 2025
ec7946c
fix link text
SylvainJuge Jun 18, 2025
7ccf852
use docket image name as test param
SylvainJuge Jun 18, 2025
1027242
test for session metrics for jetty < 12
SylvainJuge Jun 18, 2025
a8793e3
try to add jetty 12 session metrics (failing)
SylvainJuge Jun 18, 2025
327b2e7
finish jetty 12 support + doc
SylvainJuge Jun 19, 2025
651b8ac
Merge branch 'main' of github.com:open-telemetry/opentelemetry-java-i…
SylvainJuge Jun 23, 2025
141263b
remove useless attributes
SylvainJuge Jun 23, 2025
905ea68
simplify technical metric attributes
SylvainJuge Jun 23, 2025
103b719
merge jetty thread metrics
SylvainJuge Jun 23, 2025
7e8de22
Merge branch 'main' of github.com:open-telemetry/opentelemetry-java-i…
SylvainJuge Jun 27, 2025
4299811
simplify metrics to the reliable ones
SylvainJuge Jun 27, 2025
a36ed8a
Merge branch 'main' of github.com:open-telemetry/opentelemetry-java-i…
SylvainJuge Jun 27, 2025
fa30d59
Merge branch 'main' of github.com:open-telemetry/opentelemetry-java-i…
SylvainJuge Jul 2, 2025
f09492a
Merge branch 'main' of github.com:open-telemetry/opentelemetry-java-i…
SylvainJuge Jul 4, 2025
3b23e6b
Merge branch 'main' of github.com:open-telemetry/opentelemetry-java-i…
SylvainJuge Jul 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion instrumentation/jmx-metrics/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ No targets are enabled by default. The supported target environments are listed

- [activemq](javaagent/activemq.md)
- [camel](javaagent/camel.md)
- [jetty](javaagent/jetty.md)
- [jetty](library/jetty.md)
- [kafka-broker](javaagent/kafka-broker.md)
- [tomcat](library/tomcat.md)
- [wildfly](javaagent/wildfly.md)
Expand Down
16 changes: 0 additions & 16 deletions instrumentation/jmx-metrics/javaagent/jetty.md

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,7 @@ class JmxMetricInsightInstallerTest {
private static final Set<String> FILES_TO_BE_TESTED =
new HashSet<>(
Arrays.asList(
"activemq.yaml",
"camel.yaml",
"hadoop.yaml",
"jetty.yaml",
"kafka-broker.yaml",
"wildfly.yaml"));
"activemq.yaml", "camel.yaml", "hadoop.yaml", "kafka-broker.yaml", "wildfly.yaml"));

@Test
void testToVerifyExistingRulesAreValid() throws Exception {
Expand Down
40 changes: 40 additions & 0 deletions instrumentation/jmx-metrics/library/jetty.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Jetty Metrics

Here is the list of metrics based on MBeans exposed by [Jetty](https://jetty.org/).

The metrics captured and their respective attributes depend on the Jetty version:
- [Jetty 12 and later](#jetty-12-and-later)
- [Jetty 9 to 11](#jetty-9-to-11)

## Jetty 12 and later

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`.

| Metric Name | Type | Attributes | Description |
|-------------------------|---------------|---------------|-------------------------------------------|
| jetty.thread.count | UpDownCounter | | The current number of threads |
| jetty.thread.limit | UpDownCounter | | The maximum number of threads in the pool |
| jetty.thread.busy.count | UpDownCounter | | The current number of busy threads |
| jetty.thread.idle.count | UpDownCounter | | The current number of idle threads |
| jetty.thread.queue.size | UpDownCounter | | The current job queue size |
| jetty.io.select.count | Counter | | The number of select calls |
| jetty.session.count | UpDownCounter | jetty.context | Current number of active sessions |

- `jetty.context` corresponds to the deployed application subfolder in `webapps` folder.

## Jetty 9 to 11

Those metrics require the following Jetty modules to be enabled : `jmx`, `http` and `stats`.

| Metric Name | Type | Attributes | Description |
|-----------------------------|---------------|---------------|-------------------------------------------|
| jetty.thread.count | UpDownCounter | | The current number of threads |
| jetty.thread.limit | UpDownCounter | | The maximum number of threads in the pool |
| jetty.thread.busy.count | UpDownCounter | | The current number of busy threads |
| jetty.thread.idle.count | UpDownCounter | | The current number of idle threads |
| jetty.thread.queue.size | UpDownCounter | | The current job queue size |
| jetty.io.select.count | Counter | | The number of select calls |
| jetty.session.created.count | Counter | jetty.context | The total number of created sessions |
| jetty.session.duration.sum | Counter | jetty.context | The cumulated session duration |

- `jetty.context` corresponds to the deployed application subfolder in `webapps` folder.
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
---
rules:

# Thread metrics
- beans:
# Jetty 12 and later
- org.eclipse.jetty.util.thread:context=*,type=queuedthreadpool,id=*
# Jetty 9 to 11
- org.eclipse.jetty.util.thread:type=queuedthreadpool,id=*
# usually a single mbean instance exists, thus the metric is aggregated (sum for updowncounter)
prefix: jetty.thread.
unit: "{thread}"
type: updowncounter
mapping:
# jetty.thread.count
threads:
metric: count
desc: The current number of threads
# jetty.thread.limit
maxThreads:
metric: limit
desc: The configured maximum number of threads in the pool
# jetty.thread.idle.count
idleThreads:
metric: idle.count
desc: The current number of idle threads
# jetty.thread.busy.count
busyThreads:
metric: busy.count
desc: The current number of busy threads
# jetty.thread.queue.size
queueSize:
metric: queue.size
desc: The current job queue size

- bean: org.eclipse.jetty.io:context=*,type=managedselector,id=*
mapping:
# jetty.select.count
selectCount:
metric: jetty.select.count
type: counter
unit: "{operation}"
desc: The number of select calls

# Session metrics for Jetty 12
- bean: org.eclipse.jetty.session:context=*,type=defaultsessioncache,id=*
# Usually a single mbean instance exists per context, thus the metric is aggregated: sum for counter,
# gauge metrics will return invalid (last-value) with more than 1 mbean instance, thus none
# is included in this provided configuration.
prefix: jetty.session.
unit: "{session}"
metricAttribute:
# 'context' corresponds to the webapp context path
jetty.context: param(context)
mapping:
# jetty.session.count
sessionsCurrent:
metric: count
type: updowncounter
desc: Current number of active sessions

# Session metrics for Jetty 9 to 11
- bean: org.eclipse.jetty.server.session:context=*,type=sessionhandler,id=*
# Usually a single mbean instance exists per context, thus the metric is aggregated: sum for counter,
# gauge metrics will return invalid (last-value) with more than 1 mbean instance, thus none
# is included in this provided configuration.
prefix: jetty.session.
metricAttribute:
# 'context' corresponds to the webapp context path
jetty.context: param(context)
mapping:
# jetty.session.created.count
sessionsCreated:
metric: created.count
unit: "{session}"
type: counter
desc: The total number of created sessions
# jetty.session.duration.sum
sessionTimeTotal:
metric: duration.sum
unit: s
type: counter
desc: The cumulated session duration
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.jmx.rules;

import static io.opentelemetry.instrumentation.jmx.rules.assertions.DataPointAttributes.attributeWithAnyValue;

import io.opentelemetry.instrumentation.jmx.rules.assertions.AttributeMatcher;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;

public class JettyIntegrationTest extends TargetSystemTest {

private static final int JETTY_PORT = 8080;

@ParameterizedTest(name = "jetty:{arguments}")
@ValueSource(ints = {9, 10, 11, 12})
void testCollectedMetrics(int jettyMajorVersion) {

List<String> yamlFiles = Collections.singletonList("jetty.yaml");

yamlFiles.forEach(this::validateYamlSyntax);

List<String> jvmArgs = new ArrayList<>();
jvmArgs.add(javaAgentJvmArgument());
jvmArgs.addAll(javaPropertiesToJvmArgs(otelConfigProperties(yamlFiles)));

Set<String> jettyModules = new HashSet<>(Arrays.asList("jmx", "http"));
if (jettyMajorVersion >= 12) {
jettyModules.add("statistics");
// required for session management
jettyModules.add("sessions");
// required for deployment support in 'webapps' folder
jettyModules.add("ee10-deploy");
} else {
// with older versions deployment and session management are available by default
jettyModules.add("stats");
}
String addModulesArg = "--add-to-startd=" + String.join(",", jettyModules);

GenericContainer<?> container =
new GenericContainer<>(
new ImageFromDockerfile()
.withDockerfileFromBuilder(
builder ->
builder
.from("jetty:" + jettyMajorVersion)
.run("java", "-jar", "/usr/local/jetty/start.jar", addModulesArg)
.run("mkdir -p /var/lib/jetty/webapps/ROOT/")
.run("touch /var/lib/jetty/webapps/ROOT/index.html")
.build()))
.withEnv("JAVA_OPTIONS", String.join(" ", jvmArgs))
.withStartupTimeout(Duration.ofMinutes(2))
.withExposedPorts(JETTY_PORT)
.waitingFor(Wait.forListeningPorts(JETTY_PORT));

copyFilesToTarget(container, yamlFiles);

startTarget(container);

verifyMetrics(createMetricsVerifier(jettyMajorVersion));
}

private static MetricsVerifier createMetricsVerifier(int jettyMajorVersion) {

MetricsVerifier verifier =
MetricsVerifier.create()
.add(
"jetty.thread.count",
metric ->
metric
.isUpDownCounter()
.hasDescription("The current number of threads")
.hasUnit("{thread}")
.hasDataPointsWithoutAttributes())
.add(
"jetty.thread.limit",
metric ->
metric
.isUpDownCounter()
.hasDescription("The configured maximum number of threads in the pool")
.hasUnit("{thread}")
.hasDataPointsWithoutAttributes())
.add(
"jetty.thread.idle.count",
metric ->
metric
.isUpDownCounter()
.hasDescription("The current number of idle threads")
.hasUnit("{thread}")
.hasDataPointsWithoutAttributes())
.add(
"jetty.thread.busy.count",
metric ->
metric
.isUpDownCounter()
.hasDescription("The current number of busy threads")
.hasUnit("{thread}")
.hasDataPointsWithoutAttributes())
.add(
"jetty.thread.queue.size",
metric ->
metric
.isUpDownCounter()
.hasDescription("The current job queue size")
.hasUnit("{thread}")
.hasDataPointsWithoutAttributes())
.add(
"jetty.select.count",
metric ->
metric
.isCounter()
.hasDescription("The number of select calls")
.hasUnit("{operation}")
.hasDataPointsWithoutAttributes());

AttributeMatcher contextAttribute = attributeWithAnyValue("jetty.context");
if (jettyMajorVersion >= 12) {
verifier.add(
"jetty.session.count",
metric ->
metric
.isUpDownCounter()
.hasDescription("Current number of active sessions")
.hasUnit("{session}")
.hasDataPointsWithOneAttribute(contextAttribute));
} else {
verifier
.add(
"jetty.session.created.count",
metric ->
metric
.isCounter()
.hasDescription("The total number of created sessions")
.hasUnit("{session}")
.hasDataPointsWithOneAttribute(contextAttribute))
.add(
"jetty.session.duration.sum",
metric ->
metric
.isCounter()
.hasDescription("The cumulated session duration")
.hasUnit("s")
.hasDataPointsWithOneAttribute(contextAttribute));
}
return verifier;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ void testCollectedMetrics(String dockerImageName, String sampleWebApplicationUrl
jvmArgs.add(javaAgentJvmArgument());
jvmArgs.addAll(javaPropertiesToJvmArgs(otelConfigProperties(yamlFiles)));

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