For now, the current implementation of JMX Insights only allows to capture numeric MBean attributes as metrics.
However, it is common to find MBean attributes that expose internal state as a string, boolean or even enum. For example, with Tomcat Catalina:type=Connector,port=* MBean where the stateName attribute (see code) and the string values come from LifeCycleState enum (code).
The JMX Gatherer in contrib provides a way to create metrics from non-numeric MBean attributes, but replicating this with YAML seems tricky.
For string attributes, we can already capture them as a metric attribute of another metric, but it has two caveats:
Prometheus exporter has this ability, and I think it would be relevant to add it here as well.
When looking at the implementation in this PR for enums, we can see that they use a "filter" on the attribute value to implement this, for example in prometheus configuration:
- pattern: 'kafka.streams<type=stream-metrics,.*client-id=(.+)><>state: RUNNING'
name: kafka_streams_state_running
help: Kafka stream client is in state RUNNING
type: GAUGE
value: 1
labels:
clientid: "$1"
- pattern: 'kafka.streams<type=stream-metrics,.*client-id=(.+)><>state: REBALANCING'
name: kafka_streams_state_rebalancing
help: Kafka stream client is in state REBALANCING
type: GAUGE
value: 1
labels:
clientid: "$1"
With this configuration:
- a
kafka_streams_state_running with value of 1 is issued when state = RUNNING
- a
kafka_streams_state_rebalancing with value of 1 is issued when state = REBALANCING
- when the
state value does not match no metric is issued
I think there are a few solutions to implement a similar feature with YAML configuration, which in the case of Tomcat could be something like this for http.server.tomcat.connector metric:
- bean: Catalina:type=Connector,port=*
unit: "1"
prefix: http.server.tomcat.
metricAttribute:
port: param(port)
mapping:
stateName:
metric: connector
value: 1
type: gauge
desc: The number of connectors in tomcat instance
metricAttribute:
state: beanattrmap(STARTED:started,STOPPED:stopped)
Here the value: 1 indicates the metric value will be a constant value of 1 and the beanattrmap allows to translate the original values. This beanattrmap function would support mapping string, boolean and enums through their string representation.
In short, the metric value will be constant, but the attributes of the metric will change over time.
As a simpler version of this, we could also capture the attribute values as-is, in which case the original upper-case values would be preserved with state: beanattr(state)
As another alternative, we could map using distinct metrics to make it closer to prometheus solution:
- bean: Catalina:type=Connector,port=*
unit: "1"
prefix: http.server.tomcat.
metricAttribute:
port: param(port)
mapping:
stateName:
metric: connector.started
value: valuematch(STARTED,1,0)
type: gauge
desc: The number of connectors in tomcat instance
metricAttribute:
state: const(started)
stateName:
metric: connector.stopped
value: valuematch(STOPPED,1,0)
type: gauge
desc: The number of connectors in tomcat instance
metricAttribute:
state: const(stopped)
Where the valuematch(XXX,1,0) function would return 0 value when attribute value does not match and 1 when it does.
Also, the YAML syntax does not allow for duplicate beans mapping.
I have the following questions that I'd like to have feedback on:
- which approach seems the most appropriate ?
- does a constant metric with changing attribute values work with otel metrics model ? For example do we need to report
0 to cancel the previous 1 when state changes ?
For now, the current implementation of JMX Insights only allows to capture numeric MBean attributes as metrics.
However, it is common to find MBean attributes that expose internal state as a string, boolean or even enum. For example, with Tomcat
Catalina:type=Connector,port=*MBean where thestateNameattribute (see code) and the string values come from LifeCycleState enum (code).The JMX Gatherer in contrib provides a way to create metrics from non-numeric MBean attributes, but replicating this with YAML seems tricky.
For string attributes, we can already capture them as a metric attribute of another metric, but it has two caveats:
Prometheus exporter has this ability, and I think it would be relevant to add it here as well.
When looking at the implementation in this PR for enums, we can see that they use a "filter" on the attribute value to implement this, for example in prometheus configuration:
With this configuration:
kafka_streams_state_runningwith value of1is issued whenstate=RUNNINGkafka_streams_state_rebalancingwith value of1is issued whenstate=REBALANCINGstatevalue does not match no metric is issuedI think there are a few solutions to implement a similar feature with YAML configuration, which in the case of Tomcat could be something like this for
http.server.tomcat.connectormetric:Here the
value: 1indicates the metric value will be a constant value of 1 and thebeanattrmapallows to translate the original values. Thisbeanattrmapfunction would support mappingstring,booleanandenumsthrough their string representation.In short, the metric value will be constant, but the attributes of the metric will change over time.
As a simpler version of this, we could also capture the attribute values as-is, in which case the original upper-case values would be preserved with
state: beanattr(state)As another alternative, we could map using distinct metrics to make it closer to prometheus solution:
Where the
valuematch(XXX,1,0)function would return0value when attribute value does not match and1when it does.Also, the YAML syntax does not allow for duplicate beans mapping.
I have the following questions that I'd like to have feedback on:
0to cancel the previous1when state changes ?