Skip to content

Commit 4ec198f

Browse files
robsundaySylvainJugetrask
authored
Jmx unit semconv alignment - Tomcat (#13650)
Co-authored-by: Sylvain Juge <[email protected]> Co-authored-by: Trask Stalnaker <[email protected]>
1 parent d64af83 commit 4ec198f

File tree

7 files changed

+263
-94
lines changed

7 files changed

+263
-94
lines changed

instrumentation/jmx-metrics/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ No targets are enabled by default. The supported target environments are listed
2929
- [camel](javaagent/camel.md)
3030
- [jetty](javaagent/jetty.md)
3131
- [kafka-broker](javaagent/kafka-broker.md)
32-
- [tomcat](javaagent/tomcat.md)
32+
- [tomcat](library/tomcat.md)
3333
- [wildfly](javaagent/wildfly.md)
3434
- [hadoop](javaagent/hadoop.md)
3535

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

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

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@
2222
import java.util.Set;
2323
import org.junit.jupiter.api.Test;
2424

25+
/**
26+
* TODO: This test will eventually go away when all yaml files are moved from javaagent to library
27+
* directory. When yaml file is moved from javaagent to library then appropriate item must be
28+
* removed from JmxMetricInsightInstallerTest#FILES_TO_BE_TESTED and corresponding test must be
29+
* added in the library.
30+
*/
2531
class JmxMetricInsightInstallerTest {
2632
private static final String PATH_TO_ALL_EXISTING_RULES = "src/main/resources/jmx/rules";
2733
private static final Set<String> FILES_TO_BE_TESTED =
@@ -32,7 +38,6 @@ class JmxMetricInsightInstallerTest {
3238
"hadoop.yaml",
3339
"jetty.yaml",
3440
"kafka-broker.yaml",
35-
"tomcat.yaml",
3641
"wildfly.yaml"));
3742

3843
@Test

instrumentation/jmx-metrics/javaagent/tomcat.md

Lines changed: 0 additions & 13 deletions
This file was deleted.
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
---
2+
# For Tomcat, the default JMX domain is "Catalina:", however with some deployments like embedded in spring-boot
3+
# we can have the "Tomcat:" domain used, thus we use both MBean names for the metrics.
4+
5+
rules:
6+
- beans:
7+
- Catalina:type=GlobalRequestProcessor,name=*
8+
- Tomcat:type=GlobalRequestProcessor,name=*
9+
prefix: tomcat.
10+
metricAttribute:
11+
tomcat.request.processor.name: param(name)
12+
mapping:
13+
errorCount:
14+
metric: error.count
15+
type: counter
16+
unit: "{error}"
17+
desc: The number of errors.
18+
requestCount:
19+
metric: request.count
20+
type: counter
21+
unit: "{request}"
22+
desc: The number of requests processed.
23+
maxTime:
24+
metric: request.duration.max
25+
type: gauge
26+
sourceUnit: ms
27+
unit: s
28+
desc: The longest request processing time.
29+
processingTime:
30+
metric: request.duration.sum
31+
type: counter
32+
sourceUnit: ms
33+
unit: s
34+
desc: Total time of processing all requests.
35+
bytesReceived:
36+
metric: &metric network.io
37+
type: &type counter
38+
unit: &unit By
39+
desc: &desc The number of bytes transmitted.
40+
metricAttribute:
41+
network.io.direction: const(receive)
42+
bytesSent:
43+
metric: *metric
44+
type: *type
45+
unit: *unit
46+
desc: *desc
47+
metricAttribute:
48+
network.io.direction: const(transmit)
49+
50+
- beans:
51+
- Catalina:type=Manager,host=localhost,context=*
52+
- Tomcat:type=Manager,host=localhost,context=*
53+
prefix: tomcat.
54+
metricAttribute:
55+
tomcat.context: param(context)
56+
mapping:
57+
activeSessions:
58+
metric: session.active.count
59+
type: updowncounter
60+
unit: "{session}"
61+
desc: The number of currently active sessions.
62+
maxActiveSessions:
63+
metric: session.active.limit
64+
type: updowncounter
65+
unit: "{session}"
66+
desc: Maximum possible number of active sessions.
67+
68+
- beans:
69+
- Catalina:type=ThreadPool,name=*
70+
- Tomcat:type=ThreadPool,name=*
71+
unit: "{thread}"
72+
prefix: tomcat.thread.
73+
type: updowncounter
74+
metricAttribute:
75+
tomcat.thread.pool.name: param(name)
76+
mapping:
77+
currentThreadCount:
78+
metric: count
79+
desc: Total thread count of the thread pool.
80+
maxThreads:
81+
metric: limit
82+
desc: Maximum possible number of threads in the thread pool.
83+
currentThreadsBusy:
84+
metric: busy.count
85+
desc: Number of busy threads in the thread pool.
86+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
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.attribute;
9+
import static io.opentelemetry.instrumentation.jmx.rules.assertions.DataPointAttributes.attributeGroup;
10+
import static io.opentelemetry.instrumentation.jmx.rules.assertions.DataPointAttributes.attributeWithAnyValue;
11+
12+
import io.opentelemetry.instrumentation.jmx.rules.assertions.AttributeMatcher;
13+
import java.time.Duration;
14+
import java.util.ArrayList;
15+
import java.util.Collections;
16+
import java.util.List;
17+
import org.junit.jupiter.params.ParameterizedTest;
18+
import org.junit.jupiter.params.provider.CsvSource;
19+
import org.testcontainers.containers.GenericContainer;
20+
import org.testcontainers.containers.wait.strategy.Wait;
21+
22+
public class TomcatIntegrationTest extends TargetSystemTest {
23+
24+
@ParameterizedTest
25+
@CsvSource({
26+
"tomcat:10.0, https://tomcat.apache.org/tomcat-10.0-doc/appdev/sample/sample.war",
27+
"tomcat:9.0, https://tomcat.apache.org/tomcat-9.0-doc/appdev/sample/sample.war"
28+
})
29+
void testCollectedMetrics(String dockerImageName, String sampleWebApplicationUrl)
30+
throws Exception {
31+
List<String> yamlFiles = Collections.singletonList("tomcat.yaml");
32+
33+
yamlFiles.forEach(this::validateYamlSyntax);
34+
35+
List<String> jvmArgs = new ArrayList<>();
36+
jvmArgs.add(javaAgentJvmArgument());
37+
jvmArgs.addAll(javaPropertiesToJvmArgs(otelConfigProperties(yamlFiles)));
38+
39+
// testing with a basic tomcat image as test application to capture JVM metrics
40+
GenericContainer<?> target =
41+
new GenericContainer<>(dockerImageName)
42+
.withEnv("CATALINA_OPTS", String.join(" ", jvmArgs))
43+
.withStartupTimeout(Duration.ofMinutes(2))
44+
.withExposedPorts(8080)
45+
.waitingFor(Wait.forListeningPorts(8080));
46+
47+
copyFilesToTarget(target, yamlFiles);
48+
49+
startTarget(target);
50+
51+
// Deploy example web application to the tomcat to enable reporting tomcat.session.active.count
52+
// metric
53+
target.execInContainer("rm", "-fr", "/usr/local/tomcat/webapps/ROOT");
54+
target.execInContainer(
55+
"curl", sampleWebApplicationUrl, "-o", "/usr/local/tomcat/webapps/ROOT.war");
56+
57+
verifyMetrics(createMetricsVerifier());
58+
}
59+
60+
private static MetricsVerifier createMetricsVerifier() {
61+
AttributeMatcher requestProcessorNameAttribute =
62+
attribute("tomcat.request.processor.name", "\"http-nio-8080\"");
63+
AttributeMatcher threadPoolNameAttribute =
64+
attribute("tomcat.thread.pool.name", "\"http-nio-8080\"");
65+
66+
return MetricsVerifier.create()
67+
.add(
68+
"tomcat.error.count",
69+
metric ->
70+
metric
71+
.hasDescription("The number of errors.")
72+
.hasUnit("{error}")
73+
.isCounter()
74+
.hasDataPointsWithOneAttribute(requestProcessorNameAttribute))
75+
.add(
76+
"tomcat.request.count",
77+
metric ->
78+
metric
79+
.hasDescription("The number of requests processed.")
80+
.hasUnit("{request}")
81+
.isCounter()
82+
.hasDataPointsWithOneAttribute(requestProcessorNameAttribute))
83+
.add(
84+
"tomcat.request.duration.max",
85+
metric ->
86+
metric
87+
.hasDescription("The longest request processing time.")
88+
.hasUnit("s")
89+
.isGauge()
90+
.hasDataPointsWithOneAttribute(requestProcessorNameAttribute))
91+
.add(
92+
"tomcat.request.duration.sum",
93+
metric ->
94+
metric
95+
.hasDescription("Total time of processing all requests.")
96+
.hasUnit("s")
97+
.isCounter()
98+
.hasDataPointsWithOneAttribute(requestProcessorNameAttribute))
99+
.add(
100+
"tomcat.network.io",
101+
metric ->
102+
metric
103+
.hasDescription("The number of bytes transmitted.")
104+
.hasUnit("By")
105+
.isCounter()
106+
.hasDataPointsWithAttributes(
107+
attributeGroup(
108+
attribute("network.io.direction", "receive"),
109+
requestProcessorNameAttribute),
110+
attributeGroup(
111+
attribute("network.io.direction", "transmit"),
112+
requestProcessorNameAttribute)))
113+
.add(
114+
"tomcat.session.active.count",
115+
metric ->
116+
metric
117+
.hasDescription("The number of currently active sessions.")
118+
.hasUnit("{session}")
119+
.isUpDownCounter()
120+
.hasDataPointsWithOneAttribute(attributeWithAnyValue("tomcat.context")))
121+
.add(
122+
"tomcat.session.active.limit",
123+
metric ->
124+
metric
125+
.hasDescription("Maximum possible number of active sessions.")
126+
.hasUnit("{session}")
127+
.isUpDownCounter()
128+
.hasDataPointsWithOneAttribute(attributeWithAnyValue("tomcat.context")))
129+
.add(
130+
"tomcat.thread.count",
131+
metric ->
132+
metric
133+
.hasDescription("Total thread count of the thread pool.")
134+
.hasUnit("{thread}")
135+
.isUpDownCounter()
136+
.hasDataPointsWithOneAttribute(threadPoolNameAttribute))
137+
.add(
138+
"tomcat.thread.limit",
139+
metric ->
140+
metric
141+
.hasDescription("Maximum possible number of threads in the thread pool.")
142+
.hasUnit("{thread}")
143+
.isUpDownCounter()
144+
.hasDataPointsWithOneAttribute(threadPoolNameAttribute))
145+
.add(
146+
"tomcat.thread.busy.count",
147+
metric ->
148+
metric
149+
.hasDescription("Number of busy threads in the thread pool.")
150+
.hasUnit("{thread}")
151+
.isUpDownCounter()
152+
.hasDataPointsWithOneAttribute(threadPoolNameAttribute));
153+
}
154+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Tomcat Metrics
2+
3+
Here is the list of metrics based on MBeans exposed by Tomcat.
4+
5+
| Metric Name | Type | Attributes | Description |
6+
|-----------------------------|---------------|-----------------------------------------------------|--------------------------------------------------------|
7+
| tomcat.session.active.count | UpDownCounter | tomcat.context | The number of currently active sessions. |
8+
| tomcat.session.active.limit | UpDownCounter | tomcat.context | Maximum possible number of active sessions. |
9+
| tomcat.error.count | Counter | tomcat.request.processor.name | The number of errors. |
10+
| tomcat.request.count | Counter | tomcat.request.processor.name | The number of requests processed. |
11+
| tomcat.request.duration.max | Gauge | tomcat.request.processor.name | The longest request processing time. |
12+
| tomcat.request.duration.sum | Counter | tomcat.request.processor.name | Total time of processing all requests. |
13+
| tomcat.network.io | Counter | tomcat.request.processor.name, network.io.direction | The number of bytes transmitted. |
14+
| tomcat.thread.count | UpDownCounter | tomcat.thread.pool.name | Total thread count of the thread pool. |
15+
| tomcat.thread.limit | UpDownCounter | tomcat.thread.pool.name | Maximum possible number of threads in the thread pool. |
16+
| tomcat.thread.busy.count | UpDownCounter | tomcat.thread.pool.name | Number of busy threads in the thread pool. |

0 commit comments

Comments
 (0)