Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
38 changes: 21 additions & 17 deletions instrumentation/jmx-metrics/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -238,56 +242,56 @@ 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
- a `*` character to provide default option and avoid enumerating all values, this value must be quoted in YAML

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ private static List<MetricExtractor> createStateMappingExtractors(
metricInfo.getMetricName(),
metricInfo.getDescription(),
null,
"",
"1",
MetricInfo.Type.UPDOWNCOUNTER);

extractors.add(new MetricExtractor(extractor, stateMetricInfo, stateMetricAttributes));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading