diff --git a/instrumentation/jmx-metrics/README.md b/instrumentation/jmx-metrics/README.md index 0ac449a32f7a..71b6b879d914 100644 --- a/instrumentation/jmx-metrics/README.md +++ b/instrumentation/jmx-metrics/README.md @@ -229,6 +229,10 @@ The metric descriptions will remain undefined, unless they are provided by the q ### 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. + +This type of metric fits the [semantic conventions recommendations for state metric](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/how-to-write-conventions/status-metrics.md), +using the `.status` suffix is compliant with the [naming recommendations](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/how-to-write-conventions/status-metrics.md#naming). + For example, with Tomcat connector, the `Catalina:type=Connector,port=*` MBean has `stateName` (of type `String`), we can define the following rule: ```yaml @@ -238,35 +242,35 @@ rules: mapping: stateName: type: state - metric: tomcat.connector + metric: tomcat.connector.status metricAttribute: port: param(port) - connector_state: + tomcat.connector.state: ok: STARTED failed: [STOPPED,FAILED] degraded: '*' ``` -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`: +For a given value of `port`, let's say `8080` This will capture the `tomcat.connector.status` metric of type `updowncounter` with value `0` or `1` and the `tomcat.connector.state` metric attribute will have a value in [`ok`,`failed`,`degraded`]. +For every sample, 3 metrics will be captured for each value of `tomcat.connector.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` +- `tomcat.connector.status` value = `1`, attributes `port` = `8080` and `tomcat.connector.state` = `ok` +- `tomcat.connector.status` value = `0`, attributes `port` = `8080` and `tomcat.connector.state` = `failed` +- `tomcat.connector.status` value = `0`, attributes `port` = `8080` and `tomcat.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` +- `tomcat.connector.status` value = `0`, attributes `port` = `8080` and `tomcat.connector.state` = `ok` +- `tomcat.connector.status` value = `1`, attributes `port` = `8080` and `tomcat.connector.state` = `failed` +- `tomcat.connector.status` value = `0`, attributes `port` = `8080` and `tomcat.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` +- `tomcat.connector.status` value = `0`, attributes `port` = `8080` and `tomcat.connector.state` = `ok` +- `tomcat.connector.status` value = `0`, attributes `port` = `8080` and `tomcat.connector.state` = `failed` +- `tomcat.connector.status` value = `1`, attributes `port` = `8080` and `tomcat.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 @@ -274,20 +278,20 @@ Each state key can be mapped to one or more values of the MBean attribute using: 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: +The default value indicated by `*` does not require a dedicated state key. For example, if we want to have `tomcat.connector.state` metric attribute with values `on` or `off`, we can use: ```yaml - connector_state: + tomcat.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: + tomcat.connector.state: on: STARTED off: '*' ``` -State metrics do not have a unit (nor source unit) and use an empty string `""` as unit. +State metrics do not need to define `unit` nor `sourceUnit` attributes, the unit of the metric will always be `1`. ### Metric attributes modifiers diff --git a/instrumentation/jmx-metrics/library/src/main/java/io/opentelemetry/instrumentation/jmx/yaml/JmxRule.java b/instrumentation/jmx-metrics/library/src/main/java/io/opentelemetry/instrumentation/jmx/yaml/JmxRule.java index 8b42d7c9f508..458b1e1e69d6 100644 --- a/instrumentation/jmx-metrics/library/src/main/java/io/opentelemetry/instrumentation/jmx/yaml/JmxRule.java +++ b/instrumentation/jmx-metrics/library/src/main/java/io/opentelemetry/instrumentation/jmx/yaml/JmxRule.java @@ -207,7 +207,7 @@ private static List createStateMappingExtractors( metricInfo.getMetricName(), metricInfo.getDescription(), null, - "", + "1", MetricInfo.Type.UPDOWNCOUNTER); extractors.add(new MetricExtractor(extractor, stateMetricInfo, stateMetricAttributes)); diff --git a/instrumentation/jmx-metrics/library/src/test/java/io/opentelemetry/instrumentation/jmx/engine/RuleParserTest.java b/instrumentation/jmx-metrics/library/src/test/java/io/opentelemetry/instrumentation/jmx/engine/RuleParserTest.java index 726aa82520ca..5e567b9bd328 100644 --- a/instrumentation/jmx-metrics/library/src/test/java/io/opentelemetry/instrumentation/jmx/engine/RuleParserTest.java +++ b/instrumentation/jmx-metrics/library/src/test/java/io/opentelemetry/instrumentation/jmx/engine/RuleParserTest.java @@ -453,8 +453,8 @@ void testStateMetricConf() throws Exception { assertThat(me.getInfo().getMetricName()).isEqualTo("state_metric"); assertThat(me.getInfo().getType()).isEqualTo(MetricInfo.Type.UPDOWNCOUNTER); assertThat(me.getInfo().getUnit()) - .describedAs("state metric unit should be an empty string") - .isEmpty(); + .describedAs("state metric unit should be 1") + .isEqualTo("1"); assertThat(me.getAttributes()).hasSize(1); MetricAttribute stateAttribute = me.getAttributes().get(0); diff --git a/instrumentation/jmx-metrics/library/src/test/java/io/opentelemetry/instrumentation/jmx/yaml/MetricStructureTest.java b/instrumentation/jmx-metrics/library/src/test/java/io/opentelemetry/instrumentation/jmx/yaml/MetricStructureTest.java index fa37327b8189..9796b5e1396a 100644 --- a/instrumentation/jmx-metrics/library/src/test/java/io/opentelemetry/instrumentation/jmx/yaml/MetricStructureTest.java +++ b/instrumentation/jmx-metrics/library/src/test/java/io/opentelemetry/instrumentation/jmx/yaml/MetricStructureTest.java @@ -80,7 +80,7 @@ void metricAttribute_beanParam(String target, String value, String expectedValue "param()", // missing parameter "param( )", // missing parameter with empty string "param(name)a", // something after parenthesis - "lowercase()", // misng target in modifier + "lowercase()", // missing target in modifier "lowercase(param(name)", // missing parenthesis for modifier "lowercase(missing(name))", // non-existing target within modifier "lowercase(param())", // missing parameter in modifier