-
Notifications
You must be signed in to change notification settings - Fork 1k
jmx state metrics #12369
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
jmx state metrics #12369
Changes from 20 commits
9272bfe
6f20784
d1a195b
3f2f151
5973b01
4fd10aa
6155206
af37bb4
6551200
376acc5
679c460
e5ff7c5
8e73f10
e9e8e83
550b003
1bb4302
ebf58ff
6c10e6d
652ab32
e24b9ae
2698be3
e4b9fe5
111c26b
96bb6cc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -221,6 +221,67 @@ Thus, the above definitions will create several metrics, named `my.kafka.streams | |
|
|
||
| The metric descriptions will remain undefined, unless they are provided by the queried MBeans. | ||
|
|
||
| ### State Metrics | ||
|
|
||
| Some JMX attributes expose current state as a non-numeric MBean attribute, in order to capture those as metrics it is recommended to use the special `state` metric type. | ||
| For example, with Tomcat connector, the `Catalina:type=Connector,port=*` MBean has `stateName` (of type `String`), we can define the following rule: | ||
|
|
||
| ```yaml | ||
| --- | ||
| rules: | ||
| - bean: Catalina:type=Connector,port=* | ||
| mapping: | ||
| stateName: | ||
| type: state | ||
| metric: tomcat.connector | ||
| metricAttribute: | ||
| port: param(port) | ||
| connector_state: | ||
| ok: STARTED | ||
| failed: [STOPPED,FAILED] | ||
| degraded: _ | ||
| ``` | ||
SylvainJuge marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| For a given value of `port`, let's say `8080` This will capture the `tomcat.connector.state` metric of type `updowncounter` with value `0` or `1` and the `state` metric attribute will have a value in [`ok`,`failed`,`degraded`]. | ||
| For every sample, 3 metrics will be captured for each value of `state` depending on the value of `stateName`: | ||
|
|
||
| When `stateName` = `STARTED`, we have: | ||
|
|
||
| - `tomcat.connector` value = `1`, attributes `port` = `8080` and `connector_state` = `ok` | ||
| - `tomcat.connector` value = `0`, attributes `port` = `8080` and `connector_state` = `failed` | ||
| - `tomcat.connector` value = `0`, attributes `port` = `8080` and `connector_state` = `degraded` | ||
|
|
||
| When `stateName` = `STOPPED` or `FAILED`, we have: | ||
|
|
||
| - `tomcat.connector` value = `0`, attributes `port` = `8080` and `connector_state` = `ok` | ||
| - `tomcat.connector` value = `1`, attributes `port` = `8080` and `connector_state` = `failed` | ||
| - `tomcat.connector` value = `0`, attributes `port` = `8080` and `connector_state` = `degraded` | ||
|
|
||
| For other values of `stateName`, we have: | ||
|
|
||
| - `tomcat.connector` value = `0`, attributes `port` = `8080` and `connector_state` = `ok` | ||
| - `tomcat.connector` value = `0`, attributes `port` = `8080` and `connector_state` = `failed` | ||
| - `tomcat.connector` value = `1`, attributes `port` = `8080` and `connector_state` = `degraded` | ||
|
|
||
| Each state key can be mapped to one or more values of the MBean attribute using: | ||
| - a string literal or a string array | ||
| - a `_` character to provide default option and avoid enumerating all values. | ||
SylvainJuge marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| Exactly one `_` value must be present in the mapping to ensure all possible values of the MBean attribute can be mapped to a state key. | ||
|
||
|
|
||
| The default value indicated by `_` does not require a dedicated state key. For example, if we want to have `connector_state` metric attribute with values `on` or `off`, we can use: | ||
| ```yaml | ||
| connector_state: | ||
| on: STARTED | ||
| off: [STOPPED,FAILED,_] | ||
| ``` | ||
| In the particular case where only two values are defined, we can simplify further by explicitly defining one state and rely on default for the other. | ||
| ```yaml | ||
| connector_state: | ||
| on: STARTED | ||
| off: _ | ||
| ``` | ||
|
|
||
| ### General Syntax | ||
|
|
||
| Here is the general description of the accepted configuration file syntax. The whole contents of the file is case-sensitive, with exception for `type` as described in the table below. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -151,7 +151,7 @@ AttributeInfo getAttributeInfo(MBeanServerConnection connection, ObjectName obje | |
|
|
||
| // Verify correctness of configuration by attempting to extract the metric value. | ||
| // The value will be discarded, but its type will be checked. | ||
| Object sampleValue = extractAttributeValue(connection, objectName, logger); | ||
| Object sampleValue = getSampleValue(connection, objectName); | ||
|
|
||
| // Only numbers can be used to generate metric values | ||
| if (sampleValue instanceof Number) { | ||
|
|
@@ -194,6 +194,11 @@ AttributeInfo getAttributeInfo(MBeanServerConnection connection, ObjectName obje | |
| return null; | ||
| } | ||
|
|
||
| @Nullable | ||
| protected Object getSampleValue(MBeanServerConnection connection, ObjectName objectName) { | ||
| return extractAttributeValue(connection, objectName, logger); | ||
| } | ||
|
Comment on lines
+198
to
+200
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. [for reviewer] this allows to bypass the sample value check for the "artificial" attribute value that we need for the state metric. |
||
|
|
||
| /** | ||
| * Extracts the specified attribute value. In case the value is a CompositeData, drills down into | ||
| * it to find the correct singleton value (usually a Number or a String). | ||
|
|
@@ -203,7 +208,7 @@ AttributeInfo getAttributeInfo(MBeanServerConnection connection, ObjectName obje | |
| * pattern | ||
| * @param logger the logger to use, may be null. Typically we want to log any issues with the | ||
| * attributes during MBean discovery, but once the attribute is successfully detected and | ||
| * confirmed to be eligble for metric evaluation, any further attribute extraction | ||
| * confirmed to be eligible for metric evaluation, any further attribute extraction | ||
| * malfunctions will be silent to avoid flooding the log. | ||
| * @return the attribute value, if found, or {@literal null} if an error occurred | ||
| */ | ||
|
|
@@ -253,7 +258,8 @@ private Object extractAttributeValue(MBeanServerConnection connection, ObjectNam | |
| } | ||
|
|
||
| @Nullable | ||
| Number extractNumericalAttribute(MBeanServerConnection connection, ObjectName objectName) { | ||
| protected Number extractNumericalAttribute( | ||
| MBeanServerConnection connection, ObjectName objectName) { | ||
| Object value = extractAttributeValue(connection, objectName); | ||
| if (value instanceof Number) { | ||
| return (Number) value; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -120,6 +120,13 @@ void enrollExtractor( | |
| } | ||
| logger.log(INFO, "Created Gauge for {0}", metricName); | ||
| } | ||
| break; | ||
| // CHECKSTYLE:OFF | ||
| case STATE: | ||
| { | ||
| // CHECKSTYLE:ON | ||
| throw new IllegalStateException("state metrics should not be registered"); | ||
| } | ||
|
Comment on lines
+125
to
+129
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. [for reviewer] this is needed to have the switch statement cover all cases. |
||
| } | ||
| } | ||
|
|
||
|
|
@@ -173,9 +180,8 @@ static Consumer<ObservableLongMeasurement> longTypeCallback(MetricExtractor extr | |
| */ | ||
| static Attributes createMetricAttributes( | ||
| MBeanServerConnection connection, ObjectName objectName, MetricExtractor extractor) { | ||
| MetricAttribute[] metricAttributes = extractor.getAttributes(); | ||
| AttributesBuilder attrBuilder = Attributes.builder(); | ||
| for (MetricAttribute metricAttribute : metricAttributes) { | ||
| for (MetricAttribute metricAttribute : extractor.getAttributes()) { | ||
| String attributeValue = metricAttribute.acquireAttributeValue(connection, objectName); | ||
| if (attributeValue != null) { | ||
| attrBuilder = attrBuilder.put(metricAttribute.getAttributeName(), attributeValue); | ||
|
|
||
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.
I just thought of open-telemetry/opentelemetry-configuration#115
though we're already not doing this in the jmx metrics (prefering yaml brevity), so this comment should not hold up this PR
@jack-berg do you think this approach (using objects for brevity) in jmx metrics module is ok long-term?
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.
If we would switch to using an array of objects, for example with
nameandvalue, then we could add a third one withdefaultattribute key with valuetrue|falseto indicate which entry would be the default instead of using a "magic value" to represent this.