-
Notifications
You must be signed in to change notification settings - Fork 947
Jmx unit semconv alignment - Tomcat #13650
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
d081c29
e1f60cd
02e8a41
dfae1ac
e272d84
2d2c264
15ad839
297fb6b
e8fdc29
185e60d
8a9bb0f
1cc4080
747ec32
816b9ed
910e837
0dc6775
1dcd568
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,78 @@ | ||||||
--- | ||||||
# For Tomcat, the default JMX domain is "Catalina:", however with some deployments like embedded in spring-boot | ||||||
# we can have the "Tomcat:" domain used, thus we use both MBean names for the metrics. | ||||||
|
||||||
rules: | ||||||
- beans: | ||||||
- Catalina:type=GlobalRequestProcessor,name=* | ||||||
- Tomcat:type=GlobalRequestProcessor,name=* | ||||||
prefix: tomcat. | ||||||
metricAttribute: | ||||||
tomcat.request_processor.name: param(name) | ||||||
mapping: | ||||||
errorCount: | ||||||
metric: error.count | ||||||
type: counter | ||||||
unit: "{error}" | ||||||
desc: The number of errors. | ||||||
requestCount: | ||||||
metric: request.count | ||||||
type: counter | ||||||
unit: "{request}" | ||||||
desc: The number of requests processed. | ||||||
maxTime: | ||||||
metric: request.duration.max | ||||||
type: gauge | ||||||
robsunday marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
sourceUnit: ms | ||||||
unit: s | ||||||
desc: The longest request processing time. | ||||||
processingTime: | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that
|
||||||
metric: request.processing_time | ||||||
type: counter | ||||||
sourceUnit: ms | ||||||
unit: s | ||||||
desc: Total time for processing all requests. | ||||||
bytesReceived: | ||||||
metric: &metric network.io | ||||||
type: &type counter | ||||||
unit: &unit By | ||||||
desc: &desc The number of bytes transmitted. | ||||||
metricAttribute: | ||||||
network.io.direction: const(receive) | ||||||
bytesSent: | ||||||
metric: *metric | ||||||
type: *type | ||||||
unit: *unit | ||||||
desc: *desc | ||||||
metricAttribute: | ||||||
network.io.direction: const(transmit) | ||||||
|
||||||
- beans: | ||||||
- Catalina:type=Manager,host=localhost,context=* | ||||||
- Tomcat:type=Manager,host=localhost,context=* | ||||||
prefix: tomcat. | ||||||
metricAttribute: | ||||||
tomcat.context: param(context) | ||||||
mapping: | ||||||
activeSessions: | ||||||
metric: active_session.count | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
In addition to renaming I would suggest to add As a side note, there are also the |
||||||
type: updowncounter | ||||||
unit: "{session}" | ||||||
desc: The number of active sessions. | ||||||
|
||||||
- beans: | ||||||
- Catalina:type=ThreadPool,name=* | ||||||
- Tomcat:type=ThreadPool,name=* | ||||||
unit: "{thread}" | ||||||
prefix: tomcat.thread. | ||||||
type: updowncounter | ||||||
metricAttribute: | ||||||
tomcat.thread_pool.name: param(name) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
This would be consistent with |
||||||
mapping: | ||||||
robsunday marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
currentThreadCount: | ||||||
metric: count | ||||||
desc: Total thread count of the thread pool. | ||||||
currentThreadsBusy: | ||||||
metric: busy.count | ||||||
desc: Number of busy threads in the thread pool. | ||||||
|
||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here we could also capture |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
/* | ||
* 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.attribute; | ||
import static io.opentelemetry.instrumentation.jmx.rules.assertions.DataPointAttributes.attributeGroup; | ||
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.Collections; | ||
import java.util.List; | ||
import org.junit.jupiter.params.ParameterizedTest; | ||
import org.junit.jupiter.params.provider.CsvSource; | ||
import org.testcontainers.containers.GenericContainer; | ||
import org.testcontainers.containers.wait.strategy.Wait; | ||
|
||
public class TomcatIntegrationTest extends TargetSystemTest { | ||
|
||
@ParameterizedTest | ||
@CsvSource({ | ||
"tomcat:10.0, https://tomcat.apache.org/tomcat-10.0-doc/appdev/sample/sample.war", | ||
"tomcat:9.0, https://tomcat.apache.org/tomcat-9.0-doc/appdev/sample/sample.war" | ||
}) | ||
void testCollectedMetrics(String dockerImageName, String sampleWebApplicationUrl) | ||
throws Exception { | ||
List<String> yamlFiles = Collections.singletonList("tomcat.yaml"); | ||
|
||
yamlFiles.forEach(this::validateYamlSyntax); | ||
|
||
List<String> jvmArgs = new ArrayList<>(); | ||
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)) | ||
.withStartupTimeout(Duration.ofMinutes(2)) | ||
.withExposedPorts(8080) | ||
.waitingFor(Wait.forListeningPorts(8080)); | ||
|
||
copyFilesToTarget(target, yamlFiles); | ||
|
||
startTarget(target); | ||
|
||
// Deploy example web application to the tomcat to enable reporting tomcat.active_session.count | ||
// metric | ||
target.execInContainer("rm", "-fr", "/usr/local/tomcat/webapps/ROOT"); | ||
target.execInContainer( | ||
"curl", sampleWebApplicationUrl, "-o", "/usr/local/tomcat/webapps/ROOT.war"); | ||
|
||
verifyMetrics(createMetricsVerifier()); | ||
} | ||
|
||
private static MetricsVerifier createMetricsVerifier() { | ||
AttributeMatcher requestProcessorNameAttribute = | ||
attribute("tomcat.request_processor.name", "\"http-nio-8080\""); | ||
AttributeMatcher threadPoolNameAttribute = | ||
attribute("tomcat.thread_pool.name", "\"http-nio-8080\""); | ||
|
||
return MetricsVerifier.create() | ||
.add( | ||
"tomcat.error.count", | ||
metric -> | ||
metric | ||
.hasDescription("The number of errors.") | ||
.hasUnit("{error}") | ||
.isCounter() | ||
.hasDataPointsWithOneAttribute(requestProcessorNameAttribute)) | ||
.add( | ||
"tomcat.request.count", | ||
metric -> | ||
metric | ||
.hasDescription("The number of requests processed.") | ||
.hasUnit("{request}") | ||
.isCounter() | ||
.hasDataPointsWithOneAttribute(requestProcessorNameAttribute)) | ||
.add( | ||
"tomcat.request.duration.max", | ||
metric -> | ||
metric | ||
.hasDescription("The longest request processing time.") | ||
.hasUnit("s") | ||
.isGauge() | ||
.hasDataPointsWithOneAttribute(requestProcessorNameAttribute)) | ||
.add( | ||
"tomcat.request.processing_time", | ||
metric -> | ||
metric | ||
.hasDescription("Total time for processing all requests.") | ||
.hasUnit("s") | ||
.isCounter() | ||
.hasDataPointsWithOneAttribute(requestProcessorNameAttribute)) | ||
.add( | ||
"tomcat.network.io", | ||
metric -> | ||
metric | ||
.hasDescription("The number of bytes transmitted.") | ||
.hasUnit("By") | ||
.isCounter() | ||
.hasDataPointsWithAttributes( | ||
attributeGroup( | ||
attribute("network.io.direction", "receive"), | ||
requestProcessorNameAttribute), | ||
attributeGroup( | ||
attribute("network.io.direction", "transmit"), | ||
requestProcessorNameAttribute))) | ||
.add( | ||
"tomcat.active_session.count", | ||
metric -> | ||
metric | ||
.hasDescription("The number of active sessions.") | ||
.hasUnit("{session}") | ||
.isUpDownCounter() | ||
.hasDataPointsWithOneAttribute(attributeWithAnyValue("tomcat.context"))) | ||
.add( | ||
"tomcat.thread.count", | ||
metric -> | ||
metric | ||
.hasDescription("Total thread count of the thread pool.") | ||
.hasUnit("{thread}") | ||
.isUpDownCounter() | ||
.hasDataPointsWithOneAttribute(threadPoolNameAttribute)) | ||
.add( | ||
"tomcat.thread.busy.count", | ||
metric -> | ||
metric | ||
.hasDescription("Number of busy threads in the thread pool.") | ||
.hasUnit("{thread}") | ||
.isUpDownCounter() | ||
.hasDataPointsWithOneAttribute(threadPoolNameAttribute)); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# Tomcat Metrics | ||
|
||
Here is the list of metrics based on MBeans exposed by Tomcat. | ||
|
||
| Metric Name | Type | Attributes | Description | | ||
|--------------------------------|---------------|-----------------------------------------------------|---------------------------------------------| | ||
| tomcat.active_session.count | UpDownCounter | tomcat.context | The number of active sessions. | | ||
| tomcat.error.count | Counter | tomcat.request_processor.name | The number of errors. | | ||
| tomcat.request.count | Counter | tomcat.request_processor.name | The number of requests processed. | | ||
| tomcat.request.duration.max | Gauge | tomcat.request_processor.name | The longest request processing time. | | ||
| tomcat.request.processing_time | Counter | tomcat.request_processor.name | Total time for processing all requests. | | ||
| tomcat.network.io | Counter | tomcat.request_processor.name, network.io.direction | The number of bytes transmitted. | | ||
| tomcat.thread.count | UpDownCounter | tomcat.thread_pool.name | Total thread count of the thread pool. | | ||
| tomcat.thread.busy.count | UpDownCounter | tomcat.thread_pool.name | Number of busy threads in the thread pool. | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[for reviewer] Tomcat metrics definition is tested in a much better way in TomcatIntegrationTest.java
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By "much better way" here it means being tested against a real tomcat instance rather than trying to parse the yaml file to see if there are any errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moreover, it can now be easily tested with multiple tomcat versions